views:

335

answers:

3

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. :)

+3  A: 

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.

Charles Salvia
+6  A: 

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
Gregory Pakosz
@Gregory: ignore my previous comment, as I'm now less certain about this. This is how I view the situation: the standard (in 9.5.1) doesn't explicitly forbid non-POD types in unions, but rather forbids types which have non-trivial constructors/destructors/assignment operators. This definition certainly overlaps with POD to an extent, but the definition of POD also forbids private member variables, which, as far as I can tell, are not excluded from unions. So it seems certain non-PODs are allowed in unions. But again, I'm not entirely certain about this.
Charles Salvia
indeed, union work with types having private member variables although those would not be considered as POD
Gregory Pakosz
@Charles > I tried to provide a more elaborate answer
Gregory Pakosz
@Charles: A class with private member attributes and trivial constructor is problematic (members would be uninitialized), so I cannot really think of a real world example where that would apply
David Rodríguez - dribeas
@dribeas: Yes, it would be odd. But the non-POD class could still have member functions which make use of those private member variables.
Charles Salvia
@ Greogory, Awesome.......... Answer :).
mahesh
+2  A: 

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.

anon