联盟内部的奇怪行为类对象

时间:2009-12-09 11:17:35

标签: c++ unions

您好我想知道以下代码的原因

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

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

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

对于Above代码,它给出错误“错误C2620:union'Test':成员't1'具有用户定义的构造函数或非平凡的默认构造函数

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

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

union Test
{
  test t1;
  test1 t2; 
};

对于上述,没有错误。

我想知道原因。

先谢谢你。 :)

3 个答案:

答案 0 :(得分:15)

根据C ++标准(§9.5.1,引用以及其他答案):

  

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

我首先链接到Wikipedia article about POD types,其中指出:

  

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

答案 1 :(得分:5)

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

  

一个对象   具有非平凡构造函数的类,   一个非平凡的复制构造函数,a   非平凡的析构函数,或者   非平凡的复制赋值运算符   不能成为工会的一员,也不能   一系列这样的对象。如果一个工会   包含静态数据成员,或   参考类型的成员,   节目形成不良。

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

答案 2 :(得分:2)

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