C ++虚函数返回types
是否有可能inheritance类实现一个不同的返回types的虚函数(不使用模板作为返回)?
在某些情况下,只要返回types与原始返回types协变 ,派生类就可以使用不同的返回types覆盖虚函数,这是合法的。 例如,请考虑以下几点:
class Base { public: virtual ~Base() {} virtual Base* clone() const = 0; }; class Derived: public Base { public: virtual Derived* clone() const { return new Derived(*this); } };
在这里, Base
定义了一个名为clone
的纯虚函数,它返回一个Base *
。 在派生实现中,使用返回typesDerived *
重写此虚函数。 尽pipe返回types与基地中的返回types不同,但这是完全安全的,因为任何时候你都会写
Base* ptr = /* ... */ Base* clone = ptr->clone();
对clone()
的调用将始终返回一个指向Base
对象的指针,因为即使它返回一个Derived*
,该指针也可隐式转换为Base*
并且该操作已定义良好。
更一般地说,函数的返回types永远不会被认为是其签名的一部分。 只要返回types是协变的,就可以用任何返回types覆盖成员函数。
是。 只要它们是协变的,返回types就允许不同。 C ++标准像这样描述它(§10.3/ 5):
重写函数的返回types应该与重写的函数的返回types相同,或者与函数的类协同。 如果函数
D::f
覆盖函数B::f
,则函数的返回types是协变的,如果满足以下条件:
- 都是指向类或类的引用98)
B::f
的返回类中的类与D::f
的返回类中的类是相同的类,或者是D::f
的返回类中的类的明确的直接或间接基类,可以在D
访问- 指针或引用都具有相同的cv限定,并且返回types
D::f
中的类types具有与返回typesB::f
的类types相同的cv限定或更less的cv限定。
脚注98指出“不允许多级指针到类或对多级指针类的引用”。
简而言之,如果D
是B
的子types,则D
中函数的返回types需要是B
函数返回types的子types。 最常见的例子是返回types本身是基于D
和B
,但是它们不一定是。 考虑到这一点,我们两个单独的types层次结构:
struct Base { /* ... */ }; struct Derived: public Base { /* ... */ }; struct B { virtual Base* func() { return new Base; } virtual ~B() { } }; struct D: public B { Derived* func() { return new Derived; } }; int main() { B* b = new D; Base* base = b->func(); delete base; delete b; }
这个工程的原因是因为func
任何调用者都期待一个Base
指针。 任何Base
指针将做。 所以,如果D::func
承诺总是返回一个Derived
指针,那么它将始终满足由祖先类制定的契约,因为任何Derived
指针都可以隐式转换为Base
指针。 因此,来电者总能得到他们所期望的。
除了允许返回types变化之外,一些语言还允许重写函数的参数types也有所不同。 当他们这样做时,他们通常需要是不相容的 。 也就是说,如果B::f
接受一个Derived*
,那么D::f
将被允许接受一个Base*
。 后代允许他们接受的内容更宽松 ,而且他们的回报也更加严格 。 C ++不允许参数types的变换。 如果你改变参数types,C ++认为它是一个全新的函数,所以你开始进入超载和隐藏。 有关此主题的更多信息,请参阅维基百科中的协变和逆变(计算机科学) 。
虚函数的派生类实现可以有一个协变返回types 。