C ++虚函数返回类型

时间:2011-01-12 03:35:54

标签: c++ inheritance virtual-functions override return-type

继承类是否有可能实现具有不同返回类型的虚函数(不使用模板作为返回)?

3 个答案:

答案 0 :(得分:76)

在某些情况下,是的,派生类使用不同的返回类型覆盖虚函数是合法的,只要返回类型是 covariant 与原始返回类型。例如,请考虑以下事项:

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 *。在派生实现中,使用返回类型Derived *覆盖此虚函数。虽然返回类型与基数不同,但这是绝对安全的,因为任何时候你都会写

Base* ptr = /* ... */
Base* clone = ptr->clone();

clone()的调用将始终返回指向Base对象的指针,因为即使它返回Derived*,该指针也可以隐式转换为Base*并且操作定义明确。

更一般地说,函数的返回类型从不被视为其签名的一部分。只要返回类型是协变的,您就可以使用任何返回类型覆盖成员函数。

答案 1 :(得分:48)

是。只要它们是covariant,返回类型就可以不同。 C ++标准就像这样描述(§10.3/ 5):

  

重写函数的返回类型应与被覆盖函数的返回类型相同,或者协变与函数类相同。如果函数D::f覆盖函数B::f,则如果满足以下条件,则函数的返回类型是协变的:

     
      
  • 都指向类或指向类 98)
  • 的引用   
  • 返回类型B::f中的类与返回类型D::f中的类相同,或者是返回类型中类的明确直接或间接基类D::f D可以访问D::f
  •   
  • 指针或引用具有相同的cv限定,并且返回类型B::f中的类类型具有与返回类型{{中的类类型相同的cv-qualification或更少的cv-qualification 1}}。
  •   

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

简而言之,如果DB的子类型,则D中函数的返回类型必须是{{1}中函数的返回类型的子类型。 1}}。最常见的示例是返回类型本身基于BD,但它们不一定是。{考虑一下,我们有两个不同的类型层次结构:

B

这可行的原因是因为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指针都可以隐式转换为{{1指针。因此,呼叫者将始终得到他们期望的结果。


除了允许返回类型变化外,某些语言还允许覆盖函数的参数类型也不同。当他们这样做时,他们通常需要逆变。也就是说,如果Derived接受Base,则B::f将被允许接受Derived*。允许后代在他们接受的内容中更宽松,并且在他们返回的内容中更严格。 C ++不允许参数类型的逆转。如果更改参数类型,C ++会将其视为一个全新的函数,因此您开始进行重载和隐藏。有关此主题的更多信息,请参阅维基百科中的Covariance and contravariance (computer science)

答案 2 :(得分:2)

虚函数的派生类实现可以有Covariant Return Type