EC读书笔记系列之15:条款32、33、34
2015-11-13 09:55
330 查看
[b]条款32 确保你的public继承塑模出is-a关系[/b]
记住:
★public继承意味着is-a。适用于base class身上的每一件事情一定也适用于derived class身上,∵每一个derived class对象也都是一个base class对象。
[b]条款33 避免遮掩继承而来的名称[/b]
记住:
★derived classes内的名称会遮掩base classes内的名称。在public继承下从来无人希望如此
★为了让被遮掩的名称再见天日,可使用using声明式或转交函数
-------------------------------------------------------------
编译器看到某个名称,其做法是逐层向外围查找各作用域。
-----------------------------
举个例子:
解决办法:使用using声明式
-----------------
有时并不想继承base classes的所有函数,这是可以理解的。但这在public继承下绝不可能发生,∵其违反了public继承所暗示的is-a关系。
例如,Derived以private形式继承Base,而唯一想继承的mf1是无参版。using声明式技术此时就不行了,∵using声明式会令继承而来的某给定名称之所有同名函数在derived class中都可见。
此时需要“转交函数”技术:
[b]条款34 区分接口继承和实现继承[/b]
记住:
★接口继承和实现继承不同。在public继承下,derived classes总是继承base class的接口
★纯虚函数只具体指定接口继承
★普通虚函数具体指定接口继承及缺省实现继承
★非虚函数具体指定接口继承以及强制性实现继承
------------------------------------------------
一种特殊情形:
基类的纯虚函数必须在derived classes中重新声明,且基类的纯虚函数在基类中也是可以给出详细定义的,这个定义也可以表现出一种缺省行为(那是derived class可能使用的,但只有在它们明确提出申请时才是)。
记住:
★public继承意味着is-a。适用于base class身上的每一件事情一定也适用于derived class身上,∵每一个derived class对象也都是一个base class对象。
[b]条款33 避免遮掩继承而来的名称[/b]
记住:
★derived classes内的名称会遮掩base classes内的名称。在public继承下从来无人希望如此
★为了让被遮掩的名称再见天日,可使用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: virtual void mf1(); //遮掩base的同名函数 void mf3(); //遮掩base的同名函数 void mf4(); ... }; Derived d; int x; ... d.mf1(); //正确,调用Derived::mf1 d.mf1(x); //错!因为Derived::mf1遮掩Base::mf1 d.mf2(); //正确,调用Base::mf2 d.mf3(); //正确,调用Derived::mf3 d.mf3(x); //错!因为Derived::mf3遮掩Base::mf3
解决办法:使用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; //让Base class内名为mf1和mf3的所有东西 using Base::mf3; //在Derived作用域内都可见(且public!!!) virtual void mf1(); void mf3(); void mf4(); ... }; Derived d; int x; ... d.mf1(); //仍正确,调用Derived::mf1 d.mf1(x); //没问题了!调用Base::mf1 d.mf2(); //仍正确,调用Base::mf2 d.mf3(); //仍正确,调用Derived::mf3 d.mf3(x); //没问题了!调用Base::mf3
-----------------
有时并不想继承base classes的所有函数,这是可以理解的。但这在public继承下绝不可能发生,∵其违反了public继承所暗示的is-a关系。
例如,Derived以private形式继承Base,而唯一想继承的mf1是无参版。using声明式技术此时就不行了,∵using声明式会令继承而来的某给定名称之所有同名函数在derived class中都可见。
此时需要“转交函数”技术:
class Base { public: virtual void mf1() = 0; //仅想继承这个 virtual void mf1( int ); ... }; class Derived : private Base { //注意是以private方式继承!!!而非public public: //???有点不能理解 virtual void mf1() { //此为转交函数,暗自inline Base::mf1(); } ... }; Derived d; int x; ... d.mf1(); //正确,调用Derived::mf1(本质是里面调用Base版!!!) d.mf1(x); //错误!Base::mf1(int)被遮掩了,同时这也达到目的 //∵我们的目的就是唯一想继承的mf1是无参版
[b]条款34 区分接口继承和实现继承[/b]
记住:
★接口继承和实现继承不同。在public继承下,derived classes总是继承base class的接口
★纯虚函数只具体指定接口继承
★普通虚函数具体指定接口继承及缺省实现继承
★非虚函数具体指定接口继承以及强制性实现继承
------------------------------------------------
一种特殊情形:
基类的纯虚函数必须在derived classes中重新声明,且基类的纯虚函数在基类中也是可以给出详细定义的,这个定义也可以表现出一种缺省行为(那是derived class可能使用的,但只有在它们明确提出申请时才是)。
class Airplane { public: virtual void fly( const Airport &destination ) = 0; //纯虚! ... }; void Airplane::fly( const Airport &destination ) { //基类纯虚函数竟也可以提供定义!!! //缺省行为 } class ModelA : public Airplane { public: virtual void fly( const Airport &destination ) { Airplane::fly( destination ); //derived class须明确提出申请!!! } ... }; class ModelB : public Airplane { public: virtual void fly( const Airport &destination ) { Airplane::fly( destination ); //derived class须明确提出申请!!! } ... }; class ModelC : public Airplane { public: virtual void fly( const Airport &destination ); //ModelC自己重新定义 ... }; void ModelC::fly( const Airport &destination ) { //属于C类型飞机自己特有的飞行方式 }
相关文章推荐
- div之间有间隙以及img和div之间有间隙的原因及解决方法
- eclipse创建android项目,无法正常预览布局文件
- js判断输入的数值大于另一个数值
- 编程和音乐:如何听音乐
- UISegmentedControl
- Oralce HotSpot Java虚拟机的内部区域总结
- ios UIView控件设置动画后添加点击事件不起作用
- 实际的软件工程如何进行处理——大道至简七八章读后感
- Liferay Portal学习笔记:portlet执行的两个阶段
- solr构建suggest命令
- 同时获取Camera预览和录像视频流
- 就业指导【黄春霞】
- kindeditor使用方法
- java IO文件操作简单基础入门例子,IO流其实没那么难
- segmented contro
- (完整版)原因可能是堆被损坏,这也说明 中或它所加载的任何DLL 中有bug】的解决
- asda
- Vim学习笔记(1):准备工作
- IBatis.net在asp.net MVC下的使用
- display tag 标签分页实例