I have the following program:
#include <initializer_list>
#include <iostream>
class A;
class nih {
public:
virtual void apply(A & a) const { std::cout << "generic" << std::endl; };
};
union niit;
class A {
public:
int s; char kau;
A() : s(1), kau('-') { }
A(std::initializer_list<niit> k);
};
class sn : public nih { int s; public: sn(int x) : s(x) { }
virtual void apply(A & a) const { a.s=s; } };
class kaun : public nih { char kau; public: kaun(char x) : kau(x) { }
virtual void apply(A & a) const { a.kau=kau; } };
union niit { sn sni; kaun kauni; nih nihi;
niit(const sn & s) : sni(s) { }
niit(const kaun & k) : kauni(k) { }
};
A::A(std::initializer_list<niit> k) {
const niit *n=k.begin();
for(int i=0;i<k.size();i++) {
const nih* p=&n[i].nihi;
p->apply(*this);
}
}
int main(int argc, char**argv) {
A r {kaun('a'),sn(91)};
std::cout << r.s << r.kau << std::endl;
}
I get the expected result, which is 91a
. However, if I change the line
p->apply(*this);
to the following:
((const nih*)(&n[i].nihi))->apply(*this);
which should be replacement with an equivalent value, it no longer works, and instead it prints:
generic
generic
0
That is, it executes the generic method from nih
. Why is that? I tried gcc 4.6 with option -std=c++0x
, in case it matters.
A union can only be used with POD types, and as such cannot have members with virtual functions or nontrivial constructors/destructors, so this is undefined behaviour. Read (taken from this answer) §9.5.1 of the standard:
A union can have member functions (including constructors and destructors), but not virtual functions. A union shall not have base classes. A union shall not be used as a base class. An object of a class with a non-trivial constructor, a non-trivial copy-constructor, a non-trivial destructor, or a non-trivial copy assignment operator cannot be a member of a union, nor can an array of such objects. If a union contains a static data member, or a member of a reference type, the program is ill-formed.
And
In certain contexts, C++ allows only POD types to be used. For example, a union in C++ cannot contain a class that has virtual functions, or nontrivial constructors or destructors. This restriction is imposed because the compiler cannot know which constructor or destructor should be called for a union.
I have the following program:
#include <initializer_list>
#include <iostream>
class A;
class nih {
public:
virtual void apply(A & a) const { std::cout << "generic" << std::endl; };
};
union niit;
class A {
public:
int s; char kau;
A() : s(1), kau('-') { }
A(std::initializer_list<niit> k);
};
class sn : public nih { int s; public: sn(int x) : s(x) { }
virtual void apply(A & a) const { a.s=s; } };
class kaun : public nih { char kau; public: kaun(char x) : kau(x) { }
virtual void apply(A & a) const { a.kau=kau; } };
union niit { sn sni; kaun kauni; nih nihi;
niit(const sn & s) : sni(s) { }
niit(const kaun & k) : kauni(k) { }
};
A::A(std::initializer_list<niit> k) {
const niit *n=k.begin();
for(int i=0;i<k.size();i++) {
const nih* p=&n[i].nihi;
p->apply(*this);
}
}
int main(int argc, char**argv) {
A r {kaun('a'),sn(91)};
std::cout << r.s << r.kau << std::endl;
}
I get the expected result, which is 91a
. However, if I change the line
p->apply(*this);
to the following:
((const nih*)(&n[i].nihi))->apply(*this);
which should be replacement with an equivalent value, it no longer works, and instead it prints:
generic
generic
0
That is, it executes the generic method from nih
. Why is that? I tried gcc 4.6 with option -std=c++0x
, in case it matters.
A union can only be used with POD types, and as such cannot have members with virtual functions or nontrivial constructors/destructors, so this is undefined behaviour. Read (taken from this answer) §9.5.1 of the standard:
A union can have member functions (including constructors and destructors), but not virtual functions. A union shall not have base classes. A union shall not be used as a base class. An object of a class with a non-trivial constructor, a non-trivial copy-constructor, a non-trivial destructor, or a non-trivial copy assignment operator cannot be a member of a union, nor can an array of such objects. If a union contains a static data member, or a member of a reference type, the program is ill-formed.
And
In certain contexts, C++ allows only POD types to be used. For example, a union in C++ cannot contain a class that has virtual functions, or nontrivial constructors or destructors. This restriction is imposed because the compiler cannot know which constructor or destructor should be called for a union.
0 commentaires:
Enregistrer un commentaire