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;
}
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.
Thanks
First of all – your constructor seems to initialize none of its members. You should choose one, for example
Then according to 9.5.4
so correct switching from knight to queen is
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?).