简体   繁体   中英

How to access class member from inner union in C++

I've a small problem:

class A {
     public:
     enum _type {TYPE1=0,TYPE2,TYPE3} type;
     union U{
         struct _type1 {
             //somme data
         } type1;

         struct _type2 {
            //some other data
            std::vector<int> v;
         } type2;

         struct _type3 {
            // some other data
         } type3;

         U() { //constuctor
            switch(type){ // access to A::type => not accept at compile time
               case TYPE1 : /*init type1*/ break;
               case TYPE2 : /* init type2 */; new(&v) std::vector<int>; break;
               case TYPE3 : /* init type3 */ break;
               default : break;
         }

         ~U(){ //I need it to delete placement new
             switch(type)
             {
                  //same probleme
                  case TYPE2: v.~vector<int>(); break;
                  default : break;
             }
        }
     }
 };

the error:

invalid use of non-static data member

As you can see, I just need to access in the union constructor to a data of the main class. I need this to deal with "unrestricted union" (data member of the union are object in reality) so I really need to use union and not a other class.

Edit: Finaly, I find a solution for this case:

class A {
    public:
        A(int t); // <= add U() code here
        ~A(); // <= add ~U()  code here
    union {
        //same union data
    }; //move to anonymous union
};

You have to pass an instance of A to the constructor, just like for anything else. The fact that the union is declared inside A is irrelevant.

Edit: You're just reinventing boost::variant , by the way.

You don't physically have any "inner union" object inside your A objects. All you did is declare a type inside another type. This affects naming and access rights, but creates no other relationships between A and U .

If you really want to physically have an object of type U as a member of objects of type A you have to declare a member of type U in class A . That will create a physical relationship between an A object and its member of type U . C++ language does not provide standard means for determining the address of the owner from its data member, but it can be achieved by some semi-legal hacks.

For example, if you declare

class A {
public:
  union U {
    ...
  };
  ...
  U u;
};

you will be able to gain access to the entire A from inside methods of U by doing

A *pa = static_cast<A *>((void *) ((char *) this - offsetof(A, u)));

This is obviously a rather inelegant hack, relying among other things of the hardcoded name u of the class member. But the technical possibility is there nevertheless.

Or you can simply pass a pointer/reference to the enveloping A object to the U object and perform access through that pointer/reference.


However, there's a problem of another nature specific to your example. You seem to be trying to access the owner class from constructor and destructor of a member subobject. Member subobjects are constructed before the owner object. And member subobjects are destructed after the owner object. This means that what you will see from U s constructor and destructor is either not yet constructed or already destructed object of type A . Trying to access the other members of the owner object (especially non-trivial ones) in this case is not a good idea.

Your constructor and destructor are at the wrong place. Move them from the union to the class A .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM