C ++:包含类实例的联合调用错误的虚函数 [英] C++: Union containing class instances calls wrong virtual function
问题描述
我遇到了一个奇怪的现象,运行以下代码:
I came across a strange phenomena upon running the following code:
#include <iostream>
class Piece {
public:
class Queen;
class Knight;
union Any;
virtual const char* name() const = 0;
};
class Piece::Queen : public Piece {
public:
virtual const char* name() const {
return "Queen";
}
};
class Piece::Knight : public Piece {
public:
virtual const char* name() const {
return "Knight";
}
};
union Piece::Any {
public:
Any() {}
Piece::Queen queen;
Piece::Knight knight;
};
using namespace std;
int main(int argc, const char* argv[]) {
Piece::Any any;
any.queen = Piece::Queen();
cout << any.queen.name() << endl;
return 0;
}
程序在Apple LLVM 3.0编译器上已成功编译,但输出为骑士。
我期望输出是皇后。
从我的测试,我看到当Piece :: Any的默认构造函数运行,它调用的Piece :: Queen和Piece :: Knights的构造函数,一个接一个。如果我要声明Piece :: Any像这样:
The program compiled successfully on the Apple LLVM 3.0 compiler, but the output was "Knight". I was expecting for the output to be "Queen". From my testing I saw that when Piece::Any's default constructor runs, it calls both Piece::Queen and Piece::Knights' constructors, one after another. If I were to declare Piece::Any like this:
union Piece::Any {
public:
Any() {}
Piece::Knight knight;
Piece::Queen queen;
};
(我基本上交换了骑士和女王的顺序),那么输出将是女王。
(I basically swapped the order of knight and queen) then the output would be Queen. Any help would be appreciated.
感谢
推荐答案
首先 - 你的构造函数似乎没有初始化它的成员。您应该选择一个,例如
First of all - your constructor seems to initialize none of its members. You should choose one, for example
Piece::Any::Any(): knight() {}
然后根据9.5.4
一般来说,必须使用显式析构函数调用和位置新运算符来更改联合的活动成员
In general, one must use explicit destructor calls and placement new operators to change the active member of a union
从骑士到女王是
any.knight.~Knight();
new(&any.queen) Queen;
如果它看起来很丑陋(就像对我一样),很清楚地表明,具有非平凡构造函数的联合对象不是一个好主意(如何boost :: variant?)。
If it looks ugly to you (as it does to me), it is clear indication, that keeping objects with non-trivial constructors in union is not a good idea (how about boost::variant?).
这篇关于C ++:包含类实例的联合调用错误的虚函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!