Consider the following:
If the void* was originally a B will it call A::print or B::print?
#include <iostream>
class A {
public:
static void w(void *p) {
A *a = reinterpret_cast<A*>(p);
a->print();
}
virtual void print() {
std::cout << "A" << std::endl;
}
};
class B : public A {
public:
void print() {
std::cout << "B" << std::endl;
}
};
int main () {
B b;
A::w(&b);
}
This prints B for me.
It seems that the void* which has been casted to an A still knows about B's overridden print function. The reason why is not immediately clear.
Can someone explain to me if this is behavior that I can rely on or if it is just some fluke that works because it is a small example (like how returning a reference to a local variable won't always segfault in small programs).
your code has undefined behavior
§ 5.2.10 Reinterpret cast
7 Converting a prvalue of type “pointer to T1” to the type “pointer to T2” (where T1 and T2 are object types and where the alignment requirements of T2 are no stricter than those of T1) and back to its original type yields the original pointer value. The result of any other such pointer conversion is unspecified.
Virtual functions are usually resolved by an implicit vtable
. This is basically an array of function pointers for every virtual function in the class hierarchy. The compiler adds it as a "hidden member" to your class. When calling a virtual function, the corresponding entry in the vtable is called.
Now, when you create a class of type B
, it implicitly has the B-vtable stored in the object. Casts do not affect this table.
Hence, when you cast your void *
to A
, the original vtable (of class B
) is present, which points to B::print
.
Note that this is implementation defined behaviour, and the standard does not guarantee anything about this. But most compilers will act like this
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With