C++中派生类隐藏(非覆盖)基类方法

 在C++中,我们通过在派生类中覆盖(override)基类方法,来实现C++的多态性(polymorphism)。派生类覆盖基类虚函数的要求是:

 1.基类的方法是virtual的;
 2. 派生类方法的形参类型必须与被覆盖的基类函数类型完全一致;
 3. 派生类的虚函数的返回类型必须和基类函数匹配。除了一种例外:当类的虚函数返回类型是类本身的指针或引用时。

 相信大家对上述规则都很清楚了,今天想讲述的是另外一种特殊情况,即:派生类隐藏了基类的方法。
 这里“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下:

 1. 如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
 2. 如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)。

 下面是一个实例

#include 
using namespace std;

class CBase
{
public:
	//three overloaded showperks()三种重载的函数
	virtual void showperks(int a) const {
		cout << "\n\t函数原型:void CBase::showperks(int a);a=" << a;
	}
	virtual void showperks(double x) const {
		cout << "\n\t函数原型: void CBase::showperks(double x);x=" << x;
	}
	virtual void showperks() const {
		cout << "\n\t函数原型: void CBase::showperks();";
	}
};

class CDerive :public CBase
{
public:
	//请注意,以下方法覆盖了基类的 void CBase::showperks(int a) 方法;
	//但是隐藏了基类的其余两种重载方法
	virtual void showperks(int a) const {
		cout << "\n\t函数原型:void CDerive::showperks(int a);a=" << a;
	}

	//如果子类想要正确的覆盖基类方法,应该补充下面两种重载形式,这里,我们暂且屏蔽
	//virtual void showperks(double x) const {
	//	cout << "\n\t函数原型: void CDerive::showperks(double x);x=" << x;
	//}
	//virtual void showperks() const {
	//	cout << "\n\t函数原型: void CDerive::showperks();";
	//}
};

int main()
{
	cout << "\n首先让我们看看派生类对象调用方法的结果:";
	CDerive cDerive;
	cDerive.showperks((int)5);
	cDerive.showperks(3.2);	//编译器在这句没报错,原因是将浮点值转为了int值,从而调用的是上面的方法
	
	//cDerive.showperks();	//请注意,编译器此处报错,原因是派生类
							//void CDerive::showperks(int a)方法隐藏了基类的的其他两种重载形式

	cout << "\n现在让我们看看基类调用方法的结果";
	CBase* pBase = &cDerive;
	pBase->showperks((int)5);
	pBase->showperks(3.2);
	pBase->showperks();
}

 对上述代码的说明:
 1. 首先,基类有showperks函数的三种重载形式,而派生类只重新定义了其中一种(原型为void showperks(int a) const);
 2. 派生类重新定义的这一个方法覆盖(override)了基类的具有相同形参的方法,但是隐藏了基类的另外两种重载形式;
 3. 由于派生类的对象隐藏了基类的两种重载形式,所以当调用cDerive.showperks()时,编译器报错。
 通过以上分析,我们可以得出一个基本的经验:如果想要覆盖基类的虚函数,应该重新定义该虚函数所有的重载形式。

你可能感兴趣的:(C/C++基础知识,c++,开发语言)