The compiler can see that a dynamic_cast from A* to A* is meaningless and therefore do nothing.
More important, however, your static_cast<A*>(getB()) results in undefined behavior because B* is not convertible to A*. Since getB() is returning void* rather than B*, the bad cast is going undetected. The compiler has to assume the static type information is accurate even though in this case it isn't (you've reinterpreted a B* as an A*). Note that the only safe form of static_cast on a void* is to the pointer type from which the void* originated.
If you change getB() to return a B* and then try the following,
dynamic_cast<A*>(getB());
or you leave the code unchanged and write this,
dynamic_cast<A*>(static_cast<B*>(getB()));
you'll get the NULL pointer you're expecting (because B* isn't convertible to A*).
If you can, it'd be good to get rid of the void* return types -- they're masking this error (and possibly others).
HTH,
Andrew
On Jul 13, 2008, at 4:37 PM, Dmitry Markman wrote:
Hi, all
I accidentally encountered the following code (not exactly of course that is very simplified version)
class V {
virtual int getID() = 0;
};
class A : public V {
public:
virtual int getID(){return 0;}
virtual int getIDA(){return 10;}
};
class B : public V {
public:
virtual int getID(){return 1;}
virtual int getIDB(){return 11;}
};
A *a = new A();
B *b = new B();
void *getA() {
return a;
}
void *getB() {
return b;
}
int main (int argc, char * const argv[]) {
A *sa = static_cast<A *>(getB());
A *aa = dynamic_cast<A *>(sa);
//here aa ISN'T NULL!!!!!
return 0;
}
in that fragment
aa isn't null
I'd expect NULL, of course
NOTE: gdb clearly shows that aa (or sa) is an instance of the B class (with set print object on and set print vtbl on)
(gdb) p aa
$2 = (B *) 0x106940
(gdb) p *aa
$3 = (B) {
<V> = {
_vptr$V = 0x2078
}, <No data fields>}
(gdb)
from other hand
the following code behaves just fine
int main (int argc, char * const argv[]) {
V *v = static_cast<V *>(getB());
A *aa = dynamic_cast<A *>(v);
//here aa IS NULL which is good
return 0;
}