【问题标题】:Why is my derived class constructor deleted?为什么我的派生类构造函数被删除了?
【发布时间】:2016-12-22 08:54:54
【问题描述】:

在下面我的编译器说找不到我的派生类构造函数:

    struct Drink
    {
        Drink(const Drink& other);
    };

    struct PepsiMax : Drink {};

    int main()
    {
        PepsiMax myPepsi;         // <--- the default constructor of PepsiMax cannot be referenced, it is a deleted function
    }

我知道需要定义 Drink 的默认构造函数,因为我创建了一个复制构造函数,编译器不会为我创建默认构造函数。但是,错误消息说它找不到我的 PepsiMax 类的默认构造函数,我希望它会生成它。如果我为 PepsiMax 定义默认构造函数,它会显示一个错误,指出它找不到 Drink 默认构造函数,这正是我所期望的。

我可以假设它指的是“Drink”而不是“PepsiMax”的默认构造函数,还是我误解了什么?我希望编译器为“PepsiMax”创建一个默认构造函数,它首先会立即调用基类构造函数。

编辑:我的困惑已经解决,感谢您的帮助。我对编译器生成的构造函数的天真解释的解释在答案中。

【问题讨论】:

  • 这是因为Drink没有默认构造函数,只有你刚刚指定的复制构造函数Drink::Drink(const Drink &)。如果需要默认构造函数,请在结构 Drink 中添加 Drink() 或在结构 PepsiMax 中添加 PepsiMax()。

标签: c++ constructor copy default


【解决方案1】:

解决办法是写

struct Drink
{
    Drink() = default;
    Drink(const Drink& other);
};

复制构造函数的存在避免了默认构造函数的自动生成(如您所知)。但这也意味着编译器无法为PepsiMax 生成默认构造函数,PepsiMax myPepsi; 所依赖的构造函数。你需要重新引入它。

【讨论】:

  • “复制构造函数的存在删除了默认构造函数。” 这似乎是一种误导性的说法,因为deletes the default constructor 可以说自 C+ 以来具有特定含义+11。
  • @Nawaz:确实你是对的。我玩过这些术语。
  • @Bathsheba Drink 的复制构造函数意味着编译器不会自动生成 DRINK 的默认构造函数,对吧?但是看到好像我没有为 PepsiMax 定义任何构造函数,它应该自动生成 PepsiMax 的默认构造函数,我会想的。错误说它找不到 PepsiMax 构造函数。
  • 但它不能自动生成默认构造函数,因为缺少Drink 默认构造函数。这就是我在回答中想要表达的意思。
  • @Bathsheba 为什么默认 PepsiMax 构造函数的自动生成依赖于 Drink 默认构造函数?我认为当我创建 PepsiMax 对象时,首先调用 PepsiMax 构造函数,然后调用基类构造函数。抱歉,我没听懂。
【解决方案2】:

当您尝试创建PepsiMax 类型的变量时,应该调用该类的默认构造函数。由于它有一个基类 (Drink),默认构造函数也将调用 Drink 的默认构造函数。现在在您的Drink 类中,您已经声明了自己的复制构造函数。这会阻止编译器自动生成默认构造函数,因此无法调用它,因此也无法生成PepsiMax 的默认构造函数。

为了防止这种情况,你应该明确告诉编译器生成一个默认构造函数

Drink() = default;

或者为Drink实现你自己的默认构造函数。

【讨论】:

  • 但是为 Drink 定义一个复制构造函数会阻止编译器为 Drink 自动生成一个默认构造函数。我没有为 PepsiMax 定义任何构造函数,所以我希望生成它的默认构造函数。但是错误消息是它找不到 PepsiMax 的默认构造函数,而不是 Drink。
  • @TitoneMaurice,无法生成 PepsiMax 的默认构造函数 - 格式错误,因为它需要调用不存在的 Drink 的默认构造函数。
【解决方案3】:

Cppreference 引号 那个

T的隐式声明或默认的默认构造函数是undefined,如果: T 有一个直接的或虚拟的基础,它有一个已删除的默认构造函数,或者它不明确或无法从此构造函数访问。

在您的示例中,由于复制构造函数的存在,Drink 类的隐式默认构造函数被 删除

随后,类PepsiMax 的隐式声明或默认默认构造函数未定义,考虑到其直接基类Drink 已删除默认构造函数。

【讨论】:

    【解决方案4】:

    我只是想补充其他人的答案。我现在明白了,只是想解释一下我的困惑。

    struct Base
    {
        Base(const Base& other);       // <---- My copy constructor, putting this here prevents the compiler generating a default and empty constructor
    };
    
    Derived : Base
    {
        // Nothing here. The compiler should generate a default constructor here
        // Something like Derived() : Base::Base() {}
    }
    

    现在,对于一个天真的人(我)来说,有两种方法可以考虑编译器是如何处理这个问题的。我的想法是编译器相当于将默认构造函数粘贴到位,然后编译。如果这是它实际所做的,那么错误消息应该与我手动粘贴该行相同,这实际上是一个不同的错误,它找不到 Base 默认构造函数,而不是 Derived 默认构造函数。

    然而,“显然”发生的是编译器试图生成:

    Derived() : Base::Base(){}
    

    解析它,找不到 Base::Base(),根本不生成该行,然后抱怨它找不到 Derived 默认构造函数。这对于那些回答的人来说是显而易见的。这里的困惑在于编译器“如何”准确地生成默认构造函数。感谢您对我的启发。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-24
      • 1970-01-01
      • 2020-07-02
      • 2013-01-28
      • 2014-06-23
      • 1970-01-01
      • 2017-12-18
      • 1970-01-01
      相关资源
      最近更新 更多