在下面的代码片段中,当方法Data :: setValue(int,int)被声明为virtual时,我收到编译器错误:
struct Data{
int ma;
int mb;
virtual void setValues(int a, int b){
ma = a;
mb = b;
}
};
struct ThreadMessage {
enum type {
DATA
};
type msg_type;
union content {
Data d;
int a;
}content;
};
编译器(g ++(Ubuntu / Linaro 4.6.3-1ubuntu5)4.6.3)给出的错误是:
struct.cpp:19:14:error:member'Data ThreadMessage :: content :: d'with 联合中不允许使用构造函数
struct.cpp:19:14:错误:成员'Data ThreadMessage :: content :: d',联合中不允许使用复制赋值运算符
这组编译错误让我完全措手不及。在实际的代码中,我有更多的属性和功能。因此,我开始查看我放置血腥运算符=()和构造函数的位置,但我没有在struct Data
中编写它们。
我知道当我将Data :: setValues设置为非虚拟时,我的问题就消失了。但为什么struct Data有构造函数?什么时候结构在C ++中有一个构造函数?当我使virtual void Data::setValues(int, int)
非虚拟时,为什么编译错误会消失?
答案 0 :(得分:3)
除了成员的默认访问权限外,struct
和class
在C ++中是相同的。
除非您仔细编程(并且使用C ++ 11),否则class
中不能有struct
或union
成员,因为这些成员的方式会有歧义应该建立联盟。
这就是你的编译器告诉你的。
答案 1 :(得分:2)
您可能想要浏览此帖子:Struct Constructor in C++?
Reader's Digest版本就像类一样,结构体有一个默认的构造函数,你可以根据需要重载和定义它。
答案 2 :(得分:1)
结构在c ++中是否具有构造函数
始终强>
错误信息有点令人困惑,但是它说你不能在那里上课。
类是使用struct
关键字或class
关键字定义的类型。
每个类都有一个构造函数和一个赋值运算符,无论它是否是用户提供的。
答案 3 :(得分:1)
编译器错误消息有点误导。从概念语言的角度来看,无论函数是否为虚函数,您的类Data
都将具有构造函数。
编译器显然是一个预C ++ 11(或者在C ++ 11之前的模式下工作)。并且它不喜欢Data
的构造函数非平凡的事实。具体来说,Data
构造函数的非平凡使编译器说Data
是一个类"有构造函数"
在这种特殊情况下,一旦在类中引入至少一个虚函数,构造函数就会变得非常简单。
非平凡的构造函数是必须执行某些操作的构造函数(在您的情况下 - 初始化支持多态的每对象家庭信息)。即它是一个必须在生成的代码中物理存在的构造函数。同时,普通构造函数仅在概念上存在,但不产生代码。当编译器将类分离为一个"时,编译器指的是物理上的区别。和#34;没有构造函数"。
答案 4 :(得分:1)
您引用的错误消息具有误导性,因此毫无疑问您想知道为什么使非虚拟函数能够解决问题。
首先 - C ++中的结构和类具有构造函数和复制赋值运算符。如果您不自己创建它们,将为您创建它们。 (您可以删除这些默认版本)。在您的示例中,有一个自动生成的Data
构造函数,并且还自动生成赋值运算符。
现在为什么错误消息会产生误导?因为他们不是真的。在C ++中,您可以使用构造函数或赋值运算符的联合成员。当这些成员函数不是微不足道时,问题就开始了。在C ++ 11之前,使用非平凡构造函数的联合成员是不可能的。 C ++ 11改变了它,但仍然没有编写其他函数,因此无法使用这种联合。
具有虚函数的结构/类具有非平凡的成员函数作为构造函数和赋值运算符(因为需要管理隐藏的数据成员)。这就是为什么当你使函数非虚拟时错误消失 - 然后成员函数变得微不足道,你的结构可以被用作联合成员而没有问题。