Consider the following code:
#include <typeinfo>
#include<iostream>
class Parent
{
public:
virtual void foo() const{};
};
class Child_A: public virtual Parent
{
};
void downcast( const Child_A& aa)
{
}
void upcast( const Parent& pp )
{
std::cout<< typeid( pp ).name() << std::endl;
downcast(pp); // line 21: This is the problematic line!
}
int main()
{
Child_A aa;
upcast(aa);
return 0;
}
I get a compiling error:
initialization.cpp:21:14: error: invalid initialization of reference of type 'const Child_A&' from expression of type 'const Parent'
downcast(pp);
But if I compile the code without line 27, typeid( pp ).name()
returns 7Child_A
.
So why do I get this error? How can I fix it? and What is really the type of pp
?
You have an implicit derived-to-base conversion on the upcast(aa)
line. pp
refers to the base class subobject contained in aa
. There is no implicit base-to-derived conversion. static_cast
can be used to perform a downcast, but since Parent
is a virtual base you'll have to use dynamic_cast
instead:
if (Child_A* c = dynamic_cast<Child_A const*>(&pp)) {
downcast(*c);
}
The line typeid(pp).name()
returns a child class output string because when applied to an object of polymorphic type (Parent
has a virtual method so it is polymorphic), the result is the most derived class:
When
typeid
is applied to a glvalue expression whose type is a polymorphic class type (10.3), the result refers to astd::type_info
object representing the type of the most derived object (1.8) (that is, the dynamic type) to which the glvalue refers.
Note that pp
's actual static type is Parent const&
. typeid
isn't a very reliable way to get the type of an object.