2

我有一个小问题:

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

错误:

无效使用非静态数据成员

如您所见,我只需要在联合构造函数中访问主类的数据。我需要这个来处理“无限制的联合”(联合的数据成员实际上是对象)所以我真的需要使用联合而不是其他类。

编辑:最后,我为这种情况找到了解决方案:

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

3 回答 3

2

您必须将 A 的实例传递给构造函数,就像其他任何事情一样。在 A 内部声明联合这一事实是无关紧要的。

编辑:顺便说一句,你只是在重新发明boost::variant

于 2012-12-26T18:43:54.550 回答
2

您的对象内部实际上没有任何“内部联合”A对象。您所做的只是在另一个类型中声明一个类型。A这会影响命名和访问权限,但不会在和之间创建其他关系U

如果您真的想在物理上将类型对象作为类型U对象的成员,则必须在 classA 中声明类型成员。这将在对象与其类型的成员之间创建物理关系。C++ 语言没有提供从数据成员中确定所有者地址的标准方法,但可以通过一些半合法的 hack 来实现。UAAU

例如,如果您声明

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

您将能够通过以下方式访问整个A内部方法U

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

这显然是一个相当不雅的hack,依赖u于类成员的硬编码名称。但技术上的可能性仍然存在。

或者您可以简单地将指向封装对象的指针/引用传递给A对象U并通过该指针/引用执行访问。


但是,您的示例存在另一个性质的问题。您似乎试图从成员子对象的构造函数析构函数访问所有者类。成员子对象在所有者对象之前构造。并且成员子对象在所有者对象之后被破坏。这意味着您将从Us 构造函数和析构函数中看到的不是尚未构造的对象,就是已经被破坏的类型的对象A。在这种情况下尝试访问所有者对象的其他成员(尤其是非平凡的成员)不是一个好主意。

于 2012-12-26T19:05:49.317 回答
0

您的构造函数和析构函数位于错误的位置。将它们从联合移动到class A.

于 2012-12-26T19:02:57.003 回答