convariant return type and override
我们都知道在类的继承体系中,想要override一个虚方法,要求新方法的函数返回类型以及函数签名同被覆盖的方法相同,也就是说,下面的代码:
#include <iostream>
using namespace std;
struct base{
virtual int func(){cout<<"base func"<<endl;return 0;}
virtual ~base(){}
};
struct derived:public base{
virtual double func() override {cout<<"derivied func"<<endl;return 3.14;}
};
int main(){
base *bp=new derived;
bp->func();
delete bp;
return 0;
}
是不能通过编译的。然而有一种例外情况,就是当新方法相对于被覆盖的方法而言,有convariant返回值类型的话,允许返回值类型不一致:
/* Inheritance hierarchies
NetServer
|
^
/ \
NetServerTCP NetServerSCTP
NetClient
|
^
/ \
NetClientTCP NetClientSCTP
*/
class NetServer {
public:
virtual NetClient* acceptConnection() = 0;
};
class NetServerTCP : public NetServer {
public:
virtual NetClientTCP* acceptConnection();
};
class NetServerSCTP : public NetServer {
public:
virtual NetClientSCTP* acceptConnection();
};
这样的override是允许的。c++标准中:
The return type of an overriding function shall be either identical to the return type of the overridden function or covariant with the classes of the functions. If a function D::f overrides a function B::f, the return type of the functions are covariant if the satisfy the following criteria:
both are pointers to classes or references to classes98)
the class in the return type of B::f is the same class as the class in the return type of D::f or, is an unambiguous direct or indirect base class of the class in the return type of D::f and is accessible in D
both pointers or references have the same cv-qualification and the class type in the return type of D::f has the same cv-qualification as or less cv-qualification than the class type in the return type of B::f.
注意第三条关于cv-qualification,举个例子就是可以这样:
struct base{
const base* func(){return this;};
};
struct derivied: public base{
derivied* func(){return this;}
};
但是不能反过来。
总结一下,covariant返回值的情况简单来说就是如果在代码的某个位置可以用D代替B(D派生自B),那么就可以使用返回值为D的指针或引用的同签名函数override B中的虚函数。
最后,记住const限定符修饰的方法与无const限定符修饰的是不同的函数,不会互相override,只会够成重载(overload)关系。
