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

mah*_*esh 5 c++ unions

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

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

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

  union Test
  {
    test t1;
    test1 t2;   
  };
}
Run Code Online (Sandbox Code Playgroud)

对于上面的代码,它给出错误" 错误C2620:联合'测试':成员't1'具有用户定义的构造函数或非平凡的默认构造函数 "

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

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

union Test
{
  test t1;
  test1 t2; 
};
Run Code Online (Sandbox Code Playgroud)

对于上面,没有错误.

我想知道原因.

先感谢您.:)

Gre*_*osz 16

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

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

我首先链接到关于POD类型维基百科文章,其中说明:

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;
}
Run Code Online (Sandbox Code Playgroud)

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

0
0
1
Run Code Online (Sandbox Code Playgroud)


Cha*_*via 6

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

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

所以你的程序不起作用,因为你明确定义了一个构造函数,因此你的对象违反了非平凡的构造函数限制.


小智 6

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