C ++中union中非平凡的struct构造函数

时间:2015-07-10 14:17:05

标签: c++ struct constructor unions

在下面的代码片段中,当方法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)非虚拟时,为什么编译错误会消失?

5 个答案:

答案 0 :(得分:3)

除了成员的默认访问权限外,structclass在C ++中是相同的。

除非您仔细编程(并且使用C ++ 11),否则class中不能有structunion成员,因为这些成员的方式会有歧义应该建立联盟。

这就是你的编译器告诉你的。

答案 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改变了它,但仍然没有编写其他函数,因此无法使用这种联合。

具有虚函数的结构/类具有非平凡的成员函数作为构造函数和赋值运算符(因为需要管理隐藏的数据成员)。这就是为什么当你使函数非虚拟时错误消失 - 然后成员函数变得微不足道,你的结构可以被用作联合成员而没有问题。