侧边栏壁纸
博主头像
如此肤浅

但行好事,莫问前程!

  • 累计撰写 52 篇文章
  • 累计创建 6 个标签
  • 累计收到 6 条评论

目 录CONTENT

文章目录

条款36 绝不重新定义继承而来的 non-virtual 函数

如此肤浅
2022-06-08 / 0 评论 / 0 点赞 / 24 阅读 / 693 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2022-06-08,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

1. 绝对不要重新定义继承而来的 non-virtual 函数。

假设类 D 继承自类 B:

class B {
public:
	void mf();
    ...
};

class D: public B { ... };
D x; // x是一个类型为D的对象

// 行为一
B* pB = &x; // 获得一个指针指向x
pB->mf(); // 通过该指针调用 mf

// 行为二
D* pD = &x; // 获得一个指针指向x
pD->mf(); // 通过该指针调用 mf

上述两种行为都通过对象 × 调用成员函数 mf。由于两者所调用的函数都相同,凭借的对象也相同,所以行为也应该相同。

但如果 mf 是个 non-virtual 函数而 D 定义有自己的 mf 版本,那就不是如此:

class D: public B {
public:
	void mf(); // 会遮掩B::mf,见条款33
    ...
};
pB->mf(); // 调用B::mf
pD->mf(); // 调用D::mf

造成此行为的原因是,non-virtual 函数如 B::mf 和 D::mf 都是静态绑定(statically bound,见条款37)。这意思是,由于 pB 被声明为一个 pointer-to-B,通过 pB 调用的 non-virtual 函数永远是 B 所定义的版本,即使 pB 指向一个类型为“B 派生之 class”的对象。但另一方面,virtual 函数却是动态绑定(dynamically bound,见条款37)。如果 mf 是个 virtual 函数,不论是通过 pB 或 pD 调用 mf,都会导致调用 D::mf,因为 pB 和 pD 真正指的都是一个类型为D的对象。

因此,任何情况下都不该重新定义一个继承而来的 non-virtual 函数!!!

0

评论区