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限定,并且返回typesD::f中的类types具有与返回typesB::f的类types相同的cv限定或更less的cv限定。

脚注98指出“不允许多级指针到类或对多级指针类的引用”。

简而言之,如果DB的子types,则D中函数的返回types需要是B函数返回types的子types。 最常见的例子是返回types本身是基于DB ,但是它们不一定是。 考虑到这一点,我们两个单独的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