In the following code, I can assign the return of the D::clone()
to a pointer to B
, but not a pointer to D
. Is is possible to return the actual polymorphic type from a call of the base pointer?
struct B
{
virtual B * clone() { return this; }
};
struct D : B
{
D * clone()
{
std::cout << std::is_same<decltype(this), D *>::value << std::endl;
return this;
}
};
int main()
{
B * b = new D();
B * bb = b->clone(); // prints "1"
std::cout << std::is_same<decltype(b->clone()), D *>::value << std::endl; // prints "0"
D * d = b->clone(); // error: invalid conversion from B * to D * (GCC 5.1)
}
No. A call of clone()
on the base B
class of a D
will return the D*
cast to a B*
.
You can reverse this by doing a static_cast<D*>
if you are absolutely certain, or a dynamic_cast<D*>
if you are not certain. If you are certain, than you should really make the variable b
be a D*
.
In C++, you should encode what you know about the state of the program at compile time regardless of the run time situation as types. By storing the D*
into B* b
, you are telling the compiler not to "know" that the data being pointed to "is a D
". Instead, you are saying "the code using B*b
should be valid for any pointer-to-B
. Clearly D* d = b->clone();
is not guaranteed to be valid for every pointer-to-B
.