条款33、避免遮掩继承而来的名称
来源:互联网 发布:蜡笔小新德朗医生 知乎 编辑:程序博客网 时间:2024/05/01 04:52
我们都知道,内层作用域会掩盖外层作用域的名称。至于名称类型是否相同并不重要,如x的int掩盖x的double.现在引入继承,当派生类成员函数涉及基类的某物(成员函数,typedef,或成员变量),编译器可以找出所涉及的东西,派生继承了声明于基类的所有东西,实际运作方式是:Drived作用域嵌套于Base类作用域内。如下:class Base{private: int x;public: virtualvoid mf1()=0; virtualvoid mf2(); void mf3(); …};class Derived:public Base{public: virtualvoid mf1(); void mf4(); …};
上述代码虽然涉及不同类型的函数及公私方式,这是为强调我们谈的是名称,和其他无关。
考虑下面派生类mf4的实现代码:void Derived::mf4(){ mf2(); ….}编译器查找规则:
local作用域(mf4覆盖的作用域)->Derived class覆盖作用域->Base作用域(本例已找到)->内含Base的那个namespace作用域(如果有)->全局作用域(global)
再考虑一个例子,重载mf1和mf3,然后在derived中添加一新的mf3:class Base{private: int x;public: virtualvoid mf1()=0; virtualvoid mf1(int); virtualvoid mf2(); void mf3(); voidmf3(double); …};class Derived:public Base{public: virtualvoid mf1(); void mf3(); void mf4(); …};
上述从名称查找规则看:基类所有名为mf1和mf3都被掩盖,故不再继承。Derived d;int x;d.mf1(); //T Derived::mf1();d.mf1(x); //F Derived::mf1掩盖Base::mf1d.mf2(); //T Base::f2d.mf3(); //T Derived::mf3d.mf3(x); //F Derived::mf3掩盖Base::mf3
显然,上述规则对所有不同参数类型适用,对虚函数与否也适用。
但有时候也会想继承重载函数,实际上:如果正在使用实际public继承却又不能继承重载函数,就是违反了B和D的is-a关系。我们可以使用using 声明达成目标:class Base{private: int x;public: virtual void mf1()=0; virtual void mf1(int); virtual void mf2(); void mf3(); void mf3(double); …};class Derived:public Base{public: using Base::mf1; //让B类中名为mf2和mf3的函数在D内作用域内都可见(且为public) using Base::mf3; virtual void mf1(); void mf3(); void mf4(); …};
现在继承机制一如继往:Derived d;int x;d.mf1(); //T Derived::mf1();d.mf1(x); //T Base::mf1d.mf2(); //T Base::f2d.mf3(); //T Derived::mf3d.mf3(x); //T Base::mf3
这意味着如果想继承基类并加上重载函数,但又想重新改写其中一部分,我们可以为那些原本会遮掩的每个名称引入一个using声明式。
但有时又不想继承基类所有函数,但在public继承中绝对不可能发生,因为public继承意味着B和D这间的is-a关系。基类的public名称在public派生类内也应该是public(这也是using声明放入D内public域内原因)
但在private继承中却是有意义的,如我们想继承的那个是无参的mf1版本,此时using声明无用。因为using声明式会令继承而来的给定名的所有同名函数在D中可见,我们可以采用不同方法,即简单的转交函数,如下:class Base{public: virtualvoid mf1()=0; virtualvoid mf1(int); … //同前};class Derived:public Base{public: virtualvoid mf1() //转交函数(forwarding function){using Base::mf1();} //暗自成为inline (TK30) …};….Derived d;int x;d.mf1(); //T 调用Derived::mf1(); d.mf1(x); //F Base::mf1被遮掩
需要记住的:
1、derived类内的名称会掩盖Base内的名称。在public继承下没人希望会这样。
2、为了让被掩盖的名称再重新可见,可以使用using声明式或转交函数。
0 0
- 条款33:避免遮掩继承而来的名称
- 条款33:避免遮掩继承而来的名称
- 条款33:避免遮掩继承而来的名称
- 条款33:避免遮掩继承而来的名称
- 条款33----避免遮掩继承而来的名称
- 条款33:避免遮掩继承而来的名称
- 条款33:避免遮掩继承而来的名称
- 条款33:避免遮掩继承而来的名称
- 条款33、避免遮掩继承而来的名称
- 条款33:避免遮掩继承而来的名称
- Effective C++条款33:避免遮掩继承而来的名称 实验示例
- 《Effective C++》学习笔记条款33 避免遮掩继承而来的名称
- Effective C++:条款33:避免遮掩继承而来的名称
- Effective C++ 读书笔记 条款33:避免遮掩继承而来的名称
- 读书笔记《Effective C++》条款33:避免遮掩继承而来的名称
- [effectiv c++]条款33:避免遮掩继承而来的名称(重载,重写,重定义)
- Effective C++ 条款33:避免遮掩继承而来的名称
- 避免遮掩继承而来的名称
- Android上使用OpenGLES2.0显示YUV数据
- TCP 的那些事儿(上)
- 电商服务已走向精细化
- linux socket的select函数例子
- 网络编程:htons、htonl、ntohs、ntohl简析
- 条款33、避免遮掩继承而来的名称
- comm命令
- mysql 学习笔记 day05
- 安卓笔记-- ListView点击和长按监听
- 机器学习中的矩阵方法03:QR 分解
- 欧几里得最大关公约数
- 自定义控件其实很简单1/12
- Struts2获取request三种方法 (2011-03-23 17:12:18)
- HDU1010 Tempter of the Bone DFS+剪枝