覆盖具有不同返回类型的虚函数

时间:2018-07-12 09:18:28

标签: c++ virtual-functions

我了解,如果返回类型是协变的,则可以使用返回类型覆盖虚拟函数。

但是我们可以使用更改后的返回类型吗?否则返回类型将隐式转换为基类函数的返回类型,例如B*A*

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;
}

似乎obj->func()返回A*而不是B*,因此出现此转换错误。

3 个答案:

答案 0 :(得分:3)

即使动态类型在实现中有所不同,静态类型检查也必须保持有效。因此,这实际上取决于所指向对象的静态类型。当您在A*上调用虚拟成员时,返回类型指定为A*

如果要在B*上调用它,则该函数的返回类型将(静态)为B*

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

每当您使用C ++处理运行时多态性时,确定接口的是对象的静态类型

答案 1 :(得分:3)

obj的静态类型为A*,因此obj->func()将使用A *A::func()声明:

  • 返回类型(A*
  • 访问说明符(public:
  • 默认参数(n / a)

动态类型为B*,因此它将调用B* B::func(),并且由于协变类型,实际上可以将其返回值转换为A*

答案 2 :(得分:0)

继承层次结构中的类型可以隐式地向下转换,在您的示例中,从BA,这也允许使用协变返回类型。但是,您尝试隐式上调,

B *obj2 = obj->func();

无效,因为objA实例,并且func()静态绑定到A提供的签名。如果必须从B*获得A::func(),则可以使用显式强制转换

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

但这是一种不好的模式,因为它损害了多态性的整个观点。