Search code examples
c++classdowncast

Invalid initialization error while upcasting and downcasting an object


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?


Solution

  • 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 a std::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.