在匿名联合中初始化类成员

时间:2015-02-23 01:52:52

标签: c++ c++11 g++ clang++

我观察到以下代码在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的初始化方式有关,但我想更好地理解这个错误。

关于coliru:http://coliru.stacked-crooked.com/a/85182239c9f033c1

1 个答案:

答案 0 :(得分:2)

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

构造函数应该使用placement new,或者它可以使用成员初始值设定项来构造一个union成员,就像在替代构造函数中一样。

如果您想在之后为b分配内容,则必须使用a销毁a.~A(),然后使用展示位置初始化b

如果联合中的成员有一个非平凡的析构函数,那么union必须有一个析构函数,它在该点使用的成员上调用析构函数。

在原始代码中,调用赋值运算符和p()方法而不先运行构造函数,从而导致崩溃。

相关问题