《Effective C++》36:绝不重新定义继承而来的non-virtual函数

请看下面这段代码:

#include <iostream>

using namespace std;

class Base
{
public:
	void Show()
	{
		cout << "I'm Base::Show()." << endl;
	}
};

class Derive : public Base
{
public:
	//遮盖了 Base::Show();
	void Show()
	{
		cout << "I'm Derive::Show()." << endl;
	}
};

int main()
{
	Derive* pD = new Derive();
	pD->Show(); //调用Derive::Show();
	
	Base* pB = new Derive();
	pB->Show(); //调用Base::Show();

	return 0;
}
实现效果:


但是,这就让我们产生疑问了,pB指针明明指向的就是Derive对象,为什么会调用 Base::Show() 呢?

这是因为非虚函数Base::Show()和Derive::Show()都是静态绑定(statically bound)的。静态绑定是指在程序编译过程中,把函数(方法或者过程)调用与响应调用所需的代码结合的过程称之为静态绑定。这就意味着,由于pB被声明为指向Base类的指针,所以通过pB指针调用的所有的非虚函数永远是Base类所定义的版本。即使pB指向一个类型为Base的派生类的对象。

与此对应,virtual函数是动态绑定(dynamically bound)的。因此就不会有上面的问题。

如:

#include <iostream>

using namespace std;

class Base
{
public:
	virtual void Show()
	{
		cout << "I'm Base::Show()." << endl;
	}
};

class Derive : public Base
{
public:
	//重写了 Base::Show();
	virtual void Show()
	{
		cout << "I'm Derive::Show()." << endl;
	}
};

int main()
{
	Derive* pD = new Derive();
	pD->Show(); //调用Derive::Show();
	
	Base* pB = new Derive();
	pB->Show(); //调用Derive::Show();

	return 0;
}
实现效果:


对于引用,也会出现类似的情况。

因此,为了避免出现类似例子一的表述不明的现象,我们一般不要重新在子类定义非虚函数。



全部评论

相关推荐

感觉自己陷入了死循环,因为不知道简历写什么所以什么也不想做,然后又什么都没做所以没得写。从三月到六月,三个月啊
零壹超人:没有简历 ➜ 不找项目 ➜ 没内容写 ➜ 更没简历 ➜ … 无限循环。你陷入了死锁,随便打破死锁的四个条件之一就可以了,打破循环等待,立即开始行动,不要等待;破坏占有且等待,立即抄一份简历先把简历写出来,再一点一点学简历上的东西
点赞 评论 收藏
分享
05-12 11:09
已编辑
门头沟学院 后端
已注销:没必要放这么多专业技能的描述。这些应该是默认已会的,写这么多行感觉在凑内容。项目这块感觉再包装包装吧,换个名字,虽然大家的项目基本都是网上套壳的,但是你这也太明显了。放一个业务项目,再放一个技术项目。技术项目,例如中间件的一些扩展和尝试。
点赞 评论 收藏
分享
鬼迹人途:你去投一投尚游游戏,服务器一面,第一个图算法,做完了给你一个策略题,你给出方案他就提出低概率问题,答不上当场给你挂
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务