《Effective C++》读书笔记 条款36:绝不重新定义继承而来的non_virtual函数

该条款告诉我们不要重新定义继承而来的non_virtual函数,因为派生如果重新定义了继承而来的non_virtual函数会将基类的该函数遮盖,不符合public继承的is-a原则。
先来看一段简单的代码

class base
{
public:
	void mf();
};

class Deriverd :public base
{

};

Deriverd D;
base *pB = &D;
B->mf();//调用base类的mf;
Deriverd *pD = &D;
pD->mf();//调用base类的mf;

上述代码可以看出,派生类public继承基类时,是继承基类的non_virtual的接口和实现的,所以通过基类和派生类指针都能访问到派生类的函数mf().但是如果给派生类也写一个mf函数,情况就不一样了

lass base
{
public:
	void mf();
};

class Deriverd :public base
{
public:
	void mf();
};

Deriverd D;
base *pB = &D;
B->mf();//调用base::mf;
Deriverd *pD = &D;
pD->mf();//调用Deriverd::mf;

由于non_virtual函数是静态绑定的所以在调用函数时指针是什么类型就会调用该类型对应的那个函数。这么看来其实也没什么,但是它违反了public继承的is-a原则。
1.适用于基类对象的每一件事也适用于派生类对象,因为每一个派生类都是一个基类对象
2.基类的派生类对象一定会继承基类的non_virtual函数的接口和实现

现在派生类重新定义了mf函数,基类对象调用基类的mf而派生了调用派生类的mf,那么就不能说派生类是一个基类对象了。就像鱼都会游泳,突然有条鱼它不游泳了,它还是鱼吗?而且mf也反映不了public继承时non_virtual应该具有的“不变性和凌驾性”,既然要变,就应该声明成virtual函数。所以为了满足public继承的is-a原则,和non_virtual函数的“不变性和凌驾性”,派生类不要重新定义non_virtual函数。

请记住:绝对不要重新定义继承而来的non_virtual函数

猜你喜欢

转载自blog.csdn.net/junya_zhang/article/details/83545710