匿名联合中 class 成员的初始化

initialization of class member in anonymous union

我观察到以下代码在行 ar.p():

处出现段错误
#include <iostream>

class A
{
public:
  virtual void p() { std::cout<<"A!\n"; }
};

class B : public A
{
public:
  void p() { std::cout<<"B!\n"; }
};

struct Param
{
  enum {AA, BB} tag;
  union {
    A a;
    B b;
  };

  Param(const A &p)
    : tag(AA) {a = p;}

  A &get() {
    switch(tag) {
    case AA: return a;
    case BB: return b;
    }
  }
};

int main() {
  A a;
  a.p();
  Param u(a);
  A &ar = u.get();
  ar.p();
}

但是,当我将 Param 构造函数更改为:

Param(const A &p)
  : tag(AA), a(p) {}

它不再出现段错误了。

我认为这与联合成员 a 的 vtable ptr 的初始化方式有关,但我想更好地理解这个错误。

关于大肠杆菌:http://coliru.stacked-crooked.com/a/85182239c9f033c1

联合没有隐式构造函数,您必须将自己的构造函数添加到联合中,以初始化联合的其中一个成员。我想这是因为编译器不知道你要初始化的是a还是b。您可能还需要赋值运算符和析构函数。另见这个问题:Why does union has deleted default constructor if one of its member doesn't have one whatsoever?

构造函数应该使用 placement new 或者它可以使用成员初始值设定项来构造联合成员之一,就像您在替代构造函数中所做的那样。

如果你之后想给 b 赋值,你必须使用 a.~A() 销毁 a,然后用新的放置初始化 b

如果联合中的成员具有非平凡的析构函数,则联合必须有一个析构函数,该析构函数调用此时使用的成员的析构函数。

在您的原始代码中,赋值运算符和 p() 方法在没有先 运行 构造函数的情况下被调用,导致崩溃。