C++虚函数返回值类型的协变(covariant)问题

先看代码:

class CBase
{
public:
	virtual int DoJob(void){
		return 0;
	}
	virtual CBase* Clone(void){
		return new CBase;
	}
	virtual CBase& GetStatic(void){
		static CBase StaticObj;
		return StaticObj;
	}
};

class CDervie1 : public CBase
{
public:
 	virtual int DoJob(void){
 		return 100;
 	}
	virtual CDervie1* Clone(void){
		return new CDervie1;
	}
	virtual CDervie1& GetStatic(void){
		static CDervie1 m_Static;
		return m_Static;
	}
};

class CDervie2 : public CDerive1
{
public:
 	virtual float DoJob(void){
 		return 1.23f;
 	}
	virtual int DoJob(void){
		return 200;
	}
	virtual CDervie2* Clone(void){
		return new CDervie2;
	}
	virtual CDervie2& GetStatic(void){
		static CDervie2 m_Static;
		return m_Static;
	}
};

class CTestVirturalBase
{
public:
	virtual CBase* GetClone(void) = 0;
	virtual CBase& GetStatic(void) = 0;
	virtual CDervie1* GetBase(void) = 0;
};

class CTestVirtualDev1 : public CTestVirturalBase
{
public:
	virtual CDervie1* GetClone(void){
		return new CDervie1;
	}
	virtual CDervie1& GetStatic(void){
		static CDervie1 StaticObj;
		return StaticObj;
	}
	virtual CBase* GetBase(void){
		return new CBase;
	}
};

上面这段代码,实际上列举了C++中两种虚函数返回数据类型的情况,那么分别来进行讨论:

1.如果父类虚函数返回的是内建数据类型,那么派生类虚函数的返回类型要与父类严格一致,否则报错,没得商量。

对于这样的规则,相信我们都不会觉得有任何争议或者意外;

2.如果父类虚函数返回的是某个父类(可以是另外一个类,比如叫CBase)的指针或引用,那么派生类虚函数的返回类型可以是CBase类的派生类(比如叫CDerive1)的指针或引用。

规则到这里发生了一点变化,C++对于返回的指针或引用类型有个特殊照顾,会检查派生类返回的与基类返回的是否有向下派生的关系,一个非常有意思的设计,一些工厂模式的实现也正是利用了这一语法特性。

那么如果父类和派生类返回的引用或指针没有向下派生的关系,比如说父类返回的是CDerive的指针,而其基类返回的是CBase指针,此时编译器果断报错,形如下文:

' class1::function1': overriding virtual function return type differs and is not covariant from 'class2::function2'

注意上面加粗的这个名词:covariant,中文翻译为协变,貌似不太常见的一个概念。

找到一段话,这里粘贴如下:

Covariance of a parameter or a return value for a virtual member function m is where its type T gets more specific in a derived class' override of m. The type T then varies (variance) in specificity in the same way (co) as the classes providing m. C++ provides language support for covariant return types that are raw pointers or raw references – the covariance is for the pointee or referent type.

解释得非常清楚,重点是协变概念仅应用于虚函数中指针或引用类型的参数返回值。注意,只要满足协变规则,那么对于虚函数的参数也可以做类似处理。

The C++ support is limited to return types because function return values are the only pure out-arguments in C++, and covariance is only type safe for a pure out-argument. Otherwise calling code could supply an object of less specific type than the receiving code expects. MIT professor Barbara Liskov investigated this and related variance type safety issues, and it's now known as the Liskov Substitution Principle, or LSP.

这里解释了为什么C++支持这种语法的原因,简单说是因为返回值是C++中唯一纯粹的输出型参数(参数列表中则做不到这一点),只要满足协变规则,那么就是类型安全的,满足里氏代换原则。

The covariance support essentially helps to avoid downcasting and dynamic type checking.

Since smart pointers are of class type one cannot use the built-in support for covariance directly for smart pointer results, but one can define apparently covariant non-virtual smart pointer result wrapper functions for a covariant virtual function that produces raw pointers.

累了,留坑,下次接着写完吧……

 

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值