匿名联合中 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 的初始化方式有关,但我想更好地理解这个错误。
联合没有隐式构造函数,您必须将自己的构造函数添加到联合中,以初始化联合的其中一个成员。我想这是因为编译器不知道你要初始化的是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()
方法在没有先 运行 构造函数的情况下被调用,导致崩溃。
我观察到以下代码在行 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 的初始化方式有关,但我想更好地理解这个错误。
联合没有隐式构造函数,您必须将自己的构造函数添加到联合中,以初始化联合的其中一个成员。我想这是因为编译器不知道你要初始化的是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()
方法在没有先 运行 构造函数的情况下被调用,导致崩溃。