我了解,如果返回类型是协变的,则可以使用返回类型覆盖虚拟函数。
但是我们可以使用更改后的返回类型吗?否则返回类型将隐式转换为基类函数的返回类型,例如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*
,因此出现此转换错误。
答案 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:
)动态类型为B*
,因此它将调用B* B::func()
,并且由于协变类型,实际上可以将其返回值转换为A*
。
答案 2 :(得分:0)
继承层次结构中的类型可以隐式地向下转换,在您的示例中,从B
到A
,这也允许使用协变返回类型。但是,您尝试隐式上调,
B *obj2 = obj->func();
无效,因为obj
是A
实例,并且func()
静态绑定到A
提供的签名。如果必须从B*
获得A::func()
,则可以使用显式强制转换
auto *obj2 = dynamic_cast<B*>(obj->func());
但这是一种不好的模式,因为它损害了多态性的整个观点。