使用不同的返回类型覆盖虚拟函数

Override virtual function with different return type

本文关键字:覆盖 虚拟 函数 返回类型      更新时间:2023-10-16

我知道,如果返回类型是协变的,那么可以使用返回类型重写虚拟函数。

但是我们可以使用更改后的返回类型吗?或者返回类型将隐式转换为基类函数的返回类型,如这里的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*,因此我得到了这个转换错误。

静态类型检查必须仍然有效,即使动态类型在实现中做了一些稍微不同的事情。因此,这实际上取决于所指向对象的静态类型。当您在A*上调用虚拟成员时,返回类型被指定为A*

如果在B*上调用它,函数的返回类型将是(静态(B*

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

无论何时在C++中处理运行时多项式,都是对象的静态类型决定了接口。

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

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

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

继承层次结构中的类型可以隐式下转换,在您的示例中从BA,这也允许协变返回类型。但你试图含蓄地向上广播,

B *obj2 = obj->func();

由于objA实例并且func()静态绑定到A提供的签名。如果必须从A::func()获得B*,则可以使用显式投射

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

但这是一种糟糕的模式,因为它损害了多态性的全部意义。