8

嗨,我想知道以下代码的原因

void main()
{
  class test
  {
    public:
      test(){}
      int k;
  };

  class test1
  {
    public:
      test1(){}
      int k;
  };

  union Test
  {
    test t1;
    test1 t2;   
  };
}

对于上面的代码,它给出了错误“错误 C2620: union 'Test': member 't1' has user-defined constructor or non-trivial default constructor

class test
{
  public:
  //test(){}
  int k;
};

class test1
{
  public:
  //test()1{}; 
  int k;
};

union Test
{
  test t1;
  test1 t2; 
};

对于以上内容,没有错误。

我想知道原因。

先感谢您。:)

4

3 回答 3

19

根据 C++ 标准(第 9.5.1 节,在其他答案中也引用了):

联合可以有成员函数(包括构造函数和析构函数),但不能有虚函数。联合不应有基类。联合不应用作基类。具有非平凡构造函数、非平凡复制构造函数、非平凡析构函数或非平凡复制赋值运算符的类的对象不能是联合的成员,也不能是此类对象的数组。如果联合包含静态数据成员或引用类型的成员,则程序格式错误。

我首先链接到关于 POD 类型的 Wikipedia 文章,该文章指出:

C++ 中的 POD 类型定义为标量类型或 POD 类。POD 类没有用户定义的复制赋值运算符,没有用户定义的析构函数,也没有本身不是 POD 的非静态数据成员。此外,POD 类必须是一个聚合类,这意味着它没有用户声明的构造函数,没有私有或受保护的非静态数据,没有基类和虚函数。该标准包括关于 POD 在 C++ 中的行为方式的声明。

在某些情况下,C++ 只允许使用 POD 类型。例如,C++ 中的联合不能包含具有虚函数或非平凡构造函数或析构函数的类。施加此限制是因为编译器无法知道应为联合调用哪个构造函数或析构函数。

第二段的第一句话可能会让你认为 C++ 只允许 POD 类型成为联合的一部分。情况并非如此,因为它允许具有私有成员的类成为联合的一部分:

#include <iostream>
using namespace std;

class test1
{
  int i;
};

class test2
{
  int i;
};

union test
{
  test1 t1;
  test2 t2;
};

int main()
{
  cout << __is_pod(test1) << endl;
  cout << __is_pod(test2) << endl;
  cout << __is_pod(test) << endl;

  return 0;
}

上面用 MSVC++ 编译的程序打印出来:

0
0
1
于 2009-12-09T11:19:40.783 回答
9

C++ 标准对可以放置在联合中的数据类型进行了某些限制。在 9.5.1 中,标准内容如下:

具有非平凡构造函数、非平凡复制构造函数、非平凡析构函数或非平凡复制赋值运算符的类的对象不能是联合的成员,也不能是此类对象的数组。如果联合包含静态数据成员或引用类型的成员,则程序格式错误。

因此,您的程序不起作用,因为您明确定义了构造函数,因此您的对象违反了非平凡的构造函数限制。

于 2009-12-09T11:19:34.717 回答
6

在 C++ 中,联合可能不包含具有(非平凡)构造函数或析构函数的类。这是因为编译器无法告诉在创建或销毁联合实例时使用哪个构造函数或析构函数。

于 2009-12-09T11:20:19.773 回答