Gaurav Sehgal
Gaurav Sehgal

Reputation: 7542

Override virtual function with different return type

I understand that virtual functions can be overridden using return type if the return type is covariant.

But can we use the changed return type? or the return type will implicitly be converted to base class' function's return type like B* to A* here.

class A
{
    public:
    virtual A *func()
    {
        A *obj=0;
        return obj;
    }
};

class B:public A
{
    public:
    virtual B *func()
    {
       B *obj =0;
       return obj;
    }
};

int main()
{
    A *obj = new B();
    obj->func();              // does in fact call B::func()
    B *obj2 = obj->func();    // throws error: invalid conversion from 'A*' to 'B*'

    return 0;
}

It seems obj->func() is returning A* and not B* and hence i get this conversion error.

Upvotes: 1

Views: 1199

Answers (3)

Jarod42
Jarod42

Reputation: 217478

Static type of obj is A* so obj->func() would use A *A::func() declaration:

  • return type (A*)
  • access specifier (public:)
  • default argument (n/a)

Dynamic type is B*, so it will call B* B::func() and thanks to covariant type would in fact convert its return value in A*.

Upvotes: 3

lubgr
lubgr

Reputation: 38287

Types in an inheritance hierarchy can implicitly be downcasted, in your example from B to A, and this allows for covariant return types, too. But you try to implicitly upcast,

B *obj2 = obj->func();

which cannot work because obj is an A instance, and func() is statically bound to the signature that A provides. If it's essential to get a B* from A::func() you can go with an explicit cast

auto *obj2 = dynamic_cast<B*>(obj->func());

but that's kind of a bad pattern, as it compromises the whole point of polymorphism.

Upvotes: 0

Static type checking must still hold, even if the dynamic type does something slightly different in the implementation. So it really depends on the static type of the object being pointed at. When you call the virtual member on an A*, the return type is specified as A*.

If you were to call it on a B*, the return type of the function would have been (statically) a B*.

B *obj = new B();
obj->func();              
B *obj2 = obj->func();   // Okay now

Whenever you deal with run-time polynorphism in C++, it's the static type of the objects that determines the interface.

Upvotes: 3

Related Questions