roro roro - 24 days ago 12
C++ Question

Trying to downcast with polymorphism, what's going wrong?

I have two pointers to a base class, one points to an actual base object and the other to a derived object. I also have a nonmember function that is overloaded for the base and derived classes. I'd like to use polymorphism to downcast the pointers so that the correct overload is called.

The output of the code is

base downcast called
base
derived downcast called
base


however the desired output is

base
derived


Can someone explain the output, and what must be done to get the desired behavior?

#include <iostream>
using namespace std;

class base
{
public:
virtual base& downcast()
{
cout << "base downcast called" << endl;
return *this;
}
};

class derived: public base
{
public:
virtual derived& downcast()
{
cout << "derived downcast called" << endl;
return *this;
}
};

void foo(const base& a)
{
cout << "base" << endl;
}

void foo(const derived& a)
{
cout << "derived" << endl;
}


int main()
{
base* ptr1 = new(base);
base* ptr2 = new(derived);

foo(ptr1->downcast());
foo(ptr2->downcast());

return 0;
}


EDIT: added cout to the downcast functions to illustrate function override/polymorphism.

AnT AnT
Answer

You are basically trying to make run-time polymorphism to affect compile-time overload resolution. This is not possible for obvious reasons. Function overloading is a compile-time feature, meaning that overload resolution is performed at compile time based on static types of function arguments.

In your case the choice of which foo to call is based on static typization: on static types of ptr1 and ptr2 and on static types of ptr1->downcast() and ptr2->downcast() return values. The latter are lvalues (references) of type base in both cases. There's no polymorphism involved in choosing foo. The compiler does not know (and does not care) that at run-time one of these base & references will actually refer to a derived object.

However, if you could call a.downcast() from foo, you would observe that rum-time polymorphism still works from inside foo. (At this time such call is not possible due to downcast() being non-const)

Comments