首页 > 代码库 > 条款37: 决不要重新定义继承而来的非虚函数
条款37: 决不要重新定义继承而来的非虚函数
class B {public: void mf(); ...};class D: public B { ... };
甚至对B,D或mf一无所知,也可以定义一个类型D的对象x,
D x; // x是类型D的一个对象
那么,如果发现这么做:
B *pB = &x; // 得到x的指针
pB->mf(); // 通过指针调用mf
和下面这么做的执行行为不一样:
D *pD = &x; // 得到x的指针
pD->mf(); // 通过指针调用mf
你一定就会感到很惊奇。
如果mf是非虚函数而D又定义了自己的mf版本,行为就不会相同:
class D: public B {public: void mf(); // 隐藏了B::mf; 参见条款50 ...};pB->mf(); // 调用B::mfpD->mf(); // 调用D::mf
名字查找与继承:(函数调用步骤)
假设调用p->mem()
1.首先确定p的静态类型
2.在p的静态类型对应的类中查找,如果找不到,则依次在直接基类中不断查找直至到达继承链的顶端,如果找遍了该类及其基类仍然找不到,编译器将报错
3.一旦找到mem,就进行常规的类型检查,以确认对于当前找到的mem,本次调用是否合法
4.假设调用合法,则编译器根据调用的是否是虚函数而产生不同的代码:
如果mem是虚函数且我们是通过引用或指针进行的调用,则编译器产生的代码将在运行时确定到底运行该虚函数的哪个版本,依据是对象的动态类型;
反之,则编译器将产生一个常规函数调用,即静态绑定
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。