我观察到以下代码在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
答案 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()
方法而不先运行构造函数,从而导致崩溃。