为什么我的编译器无法识别“ Bond()= default;”?

时间:2018-11-09 11:42:19

标签: c++ c++11

请查看此代码

class Bond
{
    public:
        Bond(int payments_per_year, int period_lengths_in_months);
        Bond() = default;

    private:
        const int payments_per_year;
        const int period_length_in_months;
    };

int main()
{
    Bond b; // Error here
}

尝试编译时出现错误:

  

错误C2280:'Bond :: Bond(void)':尝试引用已删除的函数”。

自从我添加了默认构造函数以来,这不是违反“ 3条规则”。

为什么编译器无法识别Bond() = default;

3 个答案:

答案 0 :(得分:50)

默认构造函数是 suppressed ,因为有一些常量成员需要显式初始化。

因此,由于这种抑制,编写Bond() = default不会重新引入默认构造函数。

(您可以通过删除类中的所有构造函数来看到此效果-您仍然无法实例化b。)

如果您从成员中删除const,那么一切都会好起来的;尽管另一种选择是为每个const成员提供一个
brace-or-equal-initializer ;

const int payments_per_year = 2;
const int period_length_in_months = 6;

例如。

答案 1 :(得分:25)

您正受到C ++标准草案的[class.default.ctor]p2部分(或C ++ 11中的[class.ctor]p5)的影响,

  

如果满足以下条件,则将类X的默认默认构造函数定义为已删除:
  ...
  -任何没有大括号或相等初始化器的const限定类型的非变量非静态数据成员(或其数组)都没有用户提供的默认构造函数,
  ...

解决问题的可能关键是使用不带有括号或等号初始化器的短语,因此,如果您提供括号或等号初始化器,解决您的问题,例如:

const int payments_per_year{12};
const int period_length_in_months{48};

brace-or-equal-initializer不需要大括号,我们可以看到此语法:

brace-or-equal-initializer:
    = initializer-clause
    braced-init-list

但是使用统一初始化具有一些优势,例如使narrowing conversions ill-formed值得使用它们。

gcc和clang都为此see the live godbolt session提供了更有意义的诊断。有时在多个编译器上尝试代码可能会有所帮助,特别是如果您有一个最小的测试用例,例如叮当声:

 warning: explicitly defaulted default constructor is implicitly deleted [-Wdefaulted-function-deleted]
    Bond() = default;
    ^
 note: default constructor of 'Bond' is implicitly deleted because field 'payments_per_year' of const-qualified type 'const int' would not be initialized
    const int payments_per_year;
              ^
...

答案 2 :(得分:24)

另一种解决方法是在常量的声明中指定默认值:

const int payments_per_year = {12};

这仍然可以被有价值的构造函数覆盖,但是允许默认的构造函数继续进行。

这也是简化多个构造函数案例的非常灵活的方法。