Strange Behaviour Class Objects Inside Union

2019-03-21 08:22发布

问题:

Hi I wanted know the reasons of the following code

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

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

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

For the Above code it gives error "error 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; 
};

For the Above, No Errors.

I wanted to know the Reasons.

Thank you in Advance. :)

回答1:

According to the C++ standard (§9.5.1, cited as well in other answers):

A union can have member functions (including constructors and destructors), but not virtual functions. A union shall not have base classes. A union shall not be used as a base class. An object of a class with a non-trivial constructor, a non-trivial copy-constructor, a non-trivial destructor, or a non-trivial copy assignment operator cannot be a member of a union, nor can an array of such objects. If a union contains a static data member, or a member of a reference type, the program is ill-formed.

I first linked to the Wikipedia article about POD types which states:

A POD type in C++ is defined as either a scalar type or a POD class. POD class has no user-defined copy assignment operator, no user-defined destructor, and no non-static data members that are not themselves PODs. Moreover, POD class must be an aggregate, meaning it has no user-declared constructors, no private nor protected non-static data, no bases and no virtual functions. The standard includes statements about how PODs must behave in C++.

and

In certain contexts, C++ allows only POD types to be used. For example, a union in C++ cannot contain a class that has virtual functions, or nontrivial constructors or destructors. This restriction is imposed because the compiler cannot know which constructor or destructor should be called for a union.

The first sentence of the second paragraph might make you think C++ only allows POD types to be part of a union. This isn't exactly the case as it allows a class with private members to be part of a union:

#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;
}

The program above compiled with MSVC++ prints out:

0
0
1


回答2:

The C++ standard puts certain restrictions on the types of data which can be placed inside of a union. In 9.5.1 the standard reads:

An object of a class with a non-trivial constructor, a non-trivial copy-constructor, a non-trivial destructor, or a non-trivial copy assignment operator cannot be a member of a union, nor can an array of such objects. If a union contains a static data member, or a member of a reference type, the program is ill-formed.

So your program doesn't work because you explicitly define a constructor, and therefore your object violates the non-trivial constructor restriction.



回答3:

In C++, unions may not contain classes with (non-trivial) constructors or destructors. This is because the compiler has no means of telling which constructor or destructor to use when a union instance is created or destroyed.



标签: c++ unions