Eliad
Eliad

Reputation: 926

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?

Upvotes: 0

Views: 613

Answers (2)

David G
David G

Reputation: 96845

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.

Upvotes: 3

Lingxi
Lingxi

Reputation: 14987

Downcast cannot be done implicitly. To correct it, you can make the cast explicit through either static_cast or dynamic_cast. However, since Parent is a virtual base of Child_A. Only dynamic_cast applies here. So, to make your code correct, you could change downcast(pp); to downcast(dynamic_cast<const Child_A&>(pp));. Within void upcast( const Parent& pp ), the static type of pp is Parent but its dynamic type (real type) is Child_A. typeid queries dynamic type, and that is why 7Child_A gets printed.

Upvotes: 3

Related Questions