条款32 确保你的public继承塑模出is-a关系

记住:

★public继承意味着is-a。适用于base class身上的每一件事情一定也适用于derived class身上,∵每一个derived class对象也都是一个base class对象。

条款33 避免遮掩继承而来的名称

记住:

★derived classes内的名称会遮掩base classes内的名称。在public继承下从来无人希望如此

★为了让被遮掩的名称再见天日,可使用using声明式或转交函数

-------------------------------------------------------------

编译器看到某个名称,其做法是逐层向外围查找各作用域。

-----------------------------

举个例子:

  1. class Base {
  2. private:
  3. int x;
  4. public:
  5. virtual void mf1() = ;
  6. virtual void mf1( int );
  7. virtual void mf2();
  8. void mf3();
  9. void mf3( double );
  10. ...
  11. };
  12.  
  13. class Derived : public Base {
  14.  
  15. public:
  16. virtual void mf1(); //遮掩base的同名函数
  17. void mf3(); //遮掩base的同名函数
  18. void mf4();
  19. ...
  20. };
  21.  
  22. Derived d;
  23. int x;
  24. ...
  25. d.mf1(); //正确,调用Derived::mf1
  26. d.mf1(x); //错!因为Derived::mf1遮掩Base::mf1
  27. d.mf2(); //正确,调用Base::mf2
  28. d.mf3(); //正确,调用Derived::mf3
  29. d.mf3(x); //错!因为Derived::mf3遮掩Base::mf3

解决办法:使用using声明式

  1. class Base {
  2.  
  3. private:
  4. int x;
  5. public:
  6. virtual void mf1() = ;
  7. virtual void mf1( int );
  8. virtual void mf2();
  9. void mf3();
  10. void mf3( double );
  11. ...
  12. };
  13.  
  14. class Derived : public Base {
  15.  
  16. public:
  17. using Base::mf1; //让Base class内名为mf1和mf3的所有东西
  18. using Base::mf3; //在Derived作用域内都可见(且public!!!)
  19. virtual void mf1();
  20. void mf3();
  21. void mf4();
  22. ...
  23. };
  24.  
  25. Derived d;
  26. int x;
  27. ...
  28. d.mf1(); //仍正确,调用Derived::mf1
  29. d.mf1(x); //没问题了!调用Base::mf1
  30. d.mf2(); //仍正确,调用Base::mf2
  31. d.mf3(); //仍正确,调用Derived::mf3
  32. d.mf3(x); //没问题了!调用Base::mf3

-----------------

有时并不想继承base classes的所有函数,这是可以理解的。但这在public继承下绝不可能发生,∵其违反了public继承所暗示的is-a关系。

例如,Derived以private形式继承Base,而唯一想继承的mf1是无参版。using声明式技术此时就不行了,∵using声明式会令继承而来的某给定名称之所有同名函数在derived class中都可见。

此时需要“转交函数”技术:

  1. class Base {
  2. public:
  3. virtual void mf1() = ; //仅想继承这个
  4. virtual void mf1( int );
  5. ...
  6. };
  7.  
  8. class Derived : private Base { //注意是以private方式继承!!!而非public
  9. public: //???有点不能理解
  10. virtual void mf1() { //此为转交函数,暗自inline
  11. Base::mf1();
  12. }
  13. ...
  14. };
  15.  
  16. Derived d;
  17. int x;
  18. ...
  19. d.mf1(); //正确,调用Derived::mf1(本质是里面调用Base版!!!)
  20. d.mf1(x); //错误!Base::mf1(int)被遮掩了,同时这也达到目的
  21. //∵我们的目的就是唯一想继承的mf1是无参版

条款34 区分接口继承和实现继承

记住:

★接口继承和实现继承不同。在public继承下,derived classes总是继承base class的接口

★纯虚函数只具体指定接口继承

★普通虚函数具体指定接口继承及缺省实现继承

★非虚函数具体指定接口继承以及强制性实现继承

------------------------------------------------

一种特殊情形:

基类的纯虚函数必须在derived classes中重新声明,且基类的纯虚函数在基类中也是可以给出详细定义的,这个定义也可以表现出一种缺省行为(那是derived class可能使用的,但只有在它们明确提出申请时才是)。

  1. class Airplane {
  2. public:
  3. virtual void fly( const Airport &destination ) = ; //纯虚!
  4. ...
  5. };
  6.  
  7. void Airplane::fly( const Airport &destination ) { //基类纯虚函数竟也可以提供定义!!!
  8. //缺省行为
  9. }
  10.  
  11. class ModelA : public Airplane {
  12. public:
  13. virtual void fly( const Airport &destination ) {
  14. Airplane::fly( destination ); //derived class须明确提出申请!!!
  15. }
  16. ...
  17. };
  18.  
  19. class ModelB : public Airplane {
  20. public:
  21. virtual void fly( const Airport &destination ) {
  22. Airplane::fly( destination ); //derived class须明确提出申请!!!
  23. }
  24. ...
  25. };
  26.  
  27. class ModelC : public Airplane {
  28. public:
  29. virtual void fly( const Airport &destination ); //ModelC自己重新定义
  30. ...
  31. };
  32.  
  33. void ModelC::fly( const Airport &destination ) {
  34. //属于C类型飞机自己特有的飞行方式
  35. }

EC读书笔记系列之15:条款32、33、34的更多相关文章

  1. EC读书笔记系列之8:条款13、14、15

    条款13 以对象管理资源 记住: ★为防止资源泄漏,请使用RAII对象,它们在构造函数中获得资源并在析构函数中释放 ★两个常被使用的RAII classes分别是tr1::shared_ptr和aut ...

  2. EC读书笔记系列之16:条款35、36、37、38、39、40

    条款35 考虑virtual函数以外的其他选择 记住: ★virtual函数的替代方案包括NVI手法及Strategy模式的多种形式.NVI手法自身是一个特殊形式的Template Method模式 ...

  3. EC读书笔记系列之5:条款9、条款10

    条款9 绝不在构造和析构过程中调用virtual函数 记住: ★在构造和析构期间不要调用virtual函数,∵这类调用从不下降至derived class ---------------------- ...

  4. EC读书笔记系列之1:条款1、条款2、条款3

    条款1:视C++为一个语言联邦 记住: ★C++高效编程守则视状况而变化,这取决于你使用C++的哪一部分 C: Object-oriented c++: Template c++: STL 条款2:尽 ...

  5. EC读书笔记系列之20:条款53、54、55

    条款53 不要轻忽编译器的警告 记住: ★严肃对待编译器发出的警告信息.努力在你的编译器的最高(最严苛)警告级别下争取“无任何警告”的荣誉 ★不要过度依赖编译器的报警能力,∵不同的编译器对待事情的态度 ...

  6. EC读书笔记系列之19:条款49、50、51、52

    条款49 了解new-handler的行为 记住: ★set_new_handler允许客户指定一个函数,在内存分配无法获得满足时被调用 ★Nothrow new是一个颇为局限的工具,∵其只适用于内存 ...

  7. EC读书笔记系列之18:条款47、48

    条款47 请使用traits classes表现类型信息 记住: ★Traits classes使得“类型相关信息”在编译期可用.它们以templates和“templates特化”完成实现 ★整合重 ...

  8. EC读书笔记系列之17:条款41、42、43、44、45、46

    条款41 了解隐式接口与编译器多态 记住: ★classes和templates都支持接口和多态 ★对classes而言接口是显式的(explicit),以函数签名为中心.多态则是通过virtual函 ...

  9. EC读书笔记系列之14:条款26、27、28、29、30、31

    条款26 尽可能延后变量定义式的出现时间(Lazy evaluation) 记住: ★尽可能延后变量定义式的出现.这样做可增加程序的清晰度并改善程序效率 ----------------------- ...

随机推荐

  1. 2014 ACM省赛总结

    今年ACM省赛已经过去一个星期左右了,2年的ACM训练是该做个总结了,因为前几日去參加蓝桥杯总决赛,所以没来的及写总结,如今在这小小总结一下吧-- 依晰记得去年省赛时候的样子,如今感觉那时像是个无知的 ...

  2. 关于jQuery中.attr()和.prop()

    功能需求是这样的,两个radio:男和女,一个button:重置.启动页面默认选中男,在用户选择女之后又点击重置按钮,需要恢复到默认状态. <input type="radio&quo ...

  3. Hadoop基础

    Hadoop组成 包括两个核心组成:HDFS:分布式文件系统,存储海量的数据MapReduce:并行处理框架,实现任务分解和调度 搭建大型数据仓库,PB级数据的存储.处理.分析.统计等业务(搜索引擎. ...

  4. spring boot + velocity中文乱码解决方式

    在application.properties文件中,加入如下配置: spring.velocity.properties.input.encoding=UTF-8spring.velocity.pr ...

  5. MVC5 学习资料

    http://www.cnblogs.com/HuiTai/category/591468.html

  6. 02js高级Function

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...

  7. 卸载cloudera manager

    卸载Cloudera-Manager sudo /usr/share/cmf/uninstall-cloudera-manager.sh 一直选择Yes 就好 卸载完成后,它会问你是否要将databa ...

  8. UIButton, KVC, KVO

    按钮 自定义按钮:调整内部子控件的frame 方式1:实现titleRectForContentRect:和imageRectForContentRect:方法,分别返回titleLabel和imag ...

  9. HDU 1027 - Ignatius and the Princess II

    第 m 大的 n 个数全排列 DFS可过 #include <iostream> using namespace std; int n,m; ]; bool flag; ]; void d ...

  10. [Linked List]Rotate List

    Total Accepted: 55428 Total Submissions: 250727 Difficulty: Medium Given a list, rotate the list to ...