已删除的默认构造函数(和复制控件成员)缺少规则
Missing rules for deleted default constructor (and copy control members)?
我的 c++ 书(lippman,c++ primer,第五版,第 508 页)提供了以下 4 条规则,用于确定编译器何时将复制控件和默认构造函数合成为已删除成员:
如果类具有自己的析构函数被删除或无法访问(例如私有)的成员,则合成析构函数定义为已删除。
如果类具有自己的复制构造函数已删除或无法访问的成员,则合成复制构造函数定义为已删除。如果类的成员具有已删除或无法访问的析构函数,则也会删除该类。
- 如果类具有具有已删除或无法访问析构函数的成员;或者具有没有类内初始值设定项的
如果成员具有已删除或无法访问的复制赋值运算符,或者类具有 const 或引用成员,则合成复制赋值运算符定义为已删除。
引用成员;或者具有其类型未显式定义默认构造函数且该成员没有类内初始值设定项的 const 成员,则合成的默认构造函数定义为已删除。
我看不出这些规则如何解释这里的第二个错误:
class Foo {
public:
Foo(int i) { }
};
class Bar {
private:
Foo foo;
};
int main() {
Foo foo; //error: no matching constructor in Foo
Bar bar; //error: implicitly deleted constructor in Bar
return 0;
}
第一个错误是可以理解的,与这个问题没有直接关系。第二个错误令人惊讶,因为上面的规则没有解释为什么 Bar 应该将其默认构造函数合成为已删除。
我的书缺少哪些规则,还是我没有掌握规则?
Foo
没有默认构造函数,因为您声明了一个构造函数;从 C++11 12.1/5 开始:
如果类 X 没有用户声明的构造函数,则隐式声明没有参数的构造函数 默认为
Bar
有一个已删除的默认构造函数,因为它没有默认构造函数Foo
;从 C++11 12.1/5(第 5 个项目符号点):
类 X 的默认构造函数定义为删除,如果 [...] 任何 [...] 非静态数据成员 [...] 没有默认构造函数
你引用的"规则"似乎确实没有这一点,只在第三个要点中提到了符合常量资格的成员的情况。
错误消息取决于编译器,但是,问题是Foo没有提供默认构造函数。 那个,你的规则缺少一个:
从标准 12.1
在以下情况下,类 X 的默认构造函数定义为已删除:...
任何直接或虚拟基类,或没有 大括号或等于初始值设定项,具有类类型 M(或其数组)和 M 没有默认构造函数或重载分辨率 (13.3) 为 应用于 M 的默认构造函数会导致歧义或 从默认默认值中删除或无法访问的函数 构造 函数。
由于 Foo 没有默认构造函数,因此 Bar 的构造函数被定义为已删除。
© ISO/IEC §12.1 [构造函数]:
在以下情况下,类
X
的隐式声明的默认构造函数定义为已删除:
- 任何 const 限定类型(或其数组)的非静态数据成员都没有用户提供的默认构造函数,
- 任何非静态数据成员都是引用类型,
- X 是一个类似联合的类,它有一个带有非平凡默认构造函数的变体成员
Bar
不能实例化,因为Foo
没有默认构造函数(你定义了自己的构造函数,所以编译器省略了默认构造函数);默认构造Bar
会导致使用Foo
的已删除的默认构造函数,而这无法完成;因此编译器因此隐式删除Bar
的构造函数。
唯一的方法是创建一个公共Bar
构造函数并在成员初始值设定项列表中初始化Foo
对象;以便Bar
的默认构造调用正确的foo
构造函数。例如:
class Bar {
Foo foo;
public:
Bar() : foo(0) {} // calls Foo::Foo(int) constructor
};
int main()
{
Bar bar; // okay
}
Bar
的默认构造函数可能会做什么?它必须构造一个Foo
,但不能默认构造它。编译器如何知道给Foo
的构造函数什么值?不能。因此,如果任何成员或基不是默认构造的,则编译器无法为该类创建默认构造函数。因此,标准正确地删除了Bar
的默认构造函数。
- 在createdialog创建的窗口中捕获用于编辑控件的OnMouseMove消息
- WinAPI 在单击第一个对话框上的按钮控件并销毁第一个对话框后创建第二个对话框
- 在编译时,C++项目抛出错误 C2228,这是预期的,因为控件在运行时未达到该点
- 如何更改窗体上所有控件的标题?[C++生成器]
- 双击更改 mfc 中列表控件中的行的颜色
- 派生的 wxPanel 控件如何访问其中包含 wxDialog 中的数据?
- 如何从代码本身向 wxwidgets 中的文本控件插入字符?
- 如何在MFC中的静态文本控件上插入图标?
- 我的主窗口在创建时或单击更新区域时是否会收到编辑控件?
- 如何在Qt C++中向自定义控件添加属性?
- C/C++ 检测双击 TVItem 的常用控件
- 从C++标头中导入常量而不是硬编码它们:扩展 .net 控件?
- 控件不会在选择函数旁边移动
- MFC:我们能否扩展CEditView中存在的CEdit控件类行为
- 通过嵌入式 IWebBrowser2 控件中的链接打开 youtube 搜索失败
- 查找素数:错误:控件到达非void函数的末尾
- 将控件作为成员字段传递给使用新 connect() 调用的方法
- 合成的复制控件成员总是公共的
- 在所有Windows上使用DoDataExchange/Force Update控件在一个成员变量和多个控件之间共享数据
- 已删除的默认构造函数(和复制控件成员)缺少规则