C++ C++;

C++ C++;,c++,struct,constructor,unions,C++,Struct,Constructor,Unions,在以下代码片段中,当方法Data::setValue(int,int)被声明为虚拟时,我收到一个编译器错误: struct Data{ int ma; int mb; virtual void setValues(int a, int b){ ma = a; mb = b; } }; struct ThreadMessage { enum type { DATA }; type msg_t

在以下代码片段中,当方法Data::setValue(int,int)被声明为虚拟时,我收到一个编译器错误:

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:错误:成员“Data ThreadMessage::content::d”带有 联合中不允许使用构造函数

struct.cpp:19:14:错误:联合中不允许具有复制赋值运算符的成员“Data ThreadMessage::content::d”

这组编译器错误让我完全失去了警惕。在实际代码中,我有更多的属性和函数。因此,我开始寻找我把操作符=()和构造函数放在哪里,但我没有在
struct Data
中编写它们


我知道,当我将Data::setValues设置为非虚拟时,问题就消失了。但是为什么struct数据有一个构造函数呢?结构在C++中有什么构造函数?编译C++错误时,为什么编译错误会消失::SETVALUS(INT,INT)非虚?

< P>禁止成员的默认访问,一个<代码>结构> <代码>和<代码>类< /代码>在C++中是相同的。 除非仔细编程(并使用C++11),否则在
联合中不能有
结构
成员,因为在如何构造联合的此类成员方面存在歧义


这就是编译器告诉您的。

您可能希望浏览以下线程:

《读者文摘》的版本是,与类一样,结构有一个默认构造函数,您可以随意重载和定义它

结构在c中什么时候有构造函数++

始终。

这个错误消息有点让人困惑,但它表明您不能在那里拥有一个类

类是用
struct
关键字或
class
关键字定义的类型


无论是否由用户提供,每个类都有一个构造函数和赋值运算符。

编译器错误消息有点误导。从概念语言的角度来看,无论函数是否为虚函数,在任何情况下,类
数据
都将具有构造函数

该编译器显然是C++11之前的编译器(或在C++11之前的模式下工作)。而且它不喜欢
数据
的构造函数是非平凡的这一事实。尤其是
数据
的构造函数的非平凡性使得编译器说
数据
是一个“带构造函数”的类

在这种特殊情况下,一旦在类中引入至少一个虚函数,构造函数就变得非常重要


非平凡构造函数是一个必须执行某些操作的构造函数(在您的例子中,初始化支持多态性的每个对象的家庭信息)。也就是说,它是一个构造函数,必须存在于生成的代码中。同时,一个平凡的构造函数只在概念上存在,但不生成代码。编译器在将类分为“带构造函数”类和“不带构造函数”类时引用了这种物理区别。

您引用的错误消息具有误导性,因此您无疑想知道为什么将函数设为非虚拟函数可以解决问题

<> C++中的第一个结构和类具有构造函数和复制赋值操作符。如果您不自己创建它们,它们将为您创建。(您可以删除这些默认版本)。在您的示例中,有一个自动生成的
数据的构造函数
,还有一个自动生成的赋值运算符

现在,为什么错误消息具有误导性?因为他们不是真的。在C++中,可以使用构造函数或赋值运算符。当这些成员函数不平凡时,问题就开始了。在C++11之前,不可能有具有非平凡构造函数的联合成员。C++11更改了它,但仍然没有编写额外的函数,因此不可能使用这种联合


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

当您说“我收到编译器错误,因为我从未打算将Data::setValue()设置为虚拟”时,您的意思是什么?编译器错误与联合中的值有关,因此不清楚setValue()的虚拟性与它有什么关系。@chad当我声明
virtual void Data::setValues(int,int)
void Data::setValues(int,int)
时,编译器错误消失了,这就是我的问题。如果下面的答案不能让您满意,那么这里有一个更实用的方法:考虑作为许多实现的一部分的“vtable”指针。这个指针是在构造过程中设置的,这使得相应的对象不适合存储在联合中,因为只有在构造过程中不需要任何初始化的对象才能放在彼此的顶部。我编译时确实没有--std=c++0x flagsC++没有结构(简称“structs”)。只有班级。类可以使用
struct
关键字定义,但这只是为了兼容性,并不使它们成为“structs”。(我发现这是一个解释C++程序员如何在C++中工作的更有效的方法)。它并不总是这样的:在1987之前,C++具有两个类和结构,其中的结构在C.this中是不正确的,在一个联合体中可以有结构,只要它是一个微不足道的结构。