zoukankan      html  css  js  c++  java
  • Effective C++ 33 避免遮掩继承而来的名称

      首先介绍一个原则LSP(Liskov Substitution Principle),如果Class D以Public方式继承Class B,则所有B对象可以派上用场的任何地方,D对象一样可以派上用场。

    对于重载和重写,相信大家都已经有所了解。这里讨论一下在public继承的时候,重载函数的问题。

    先看下面的例子:

     1 class Base  
     2     {  
     3     public:  
     4         virtual void mf1() = 0;  
     5         virtual void mf1(int);  
     6         virtual void mf2();  
     7         void mf3();  
     8         void mf3(double);  
     9         ...  
    10     private:  
    11         int x_;  
    12     };  
    13     class Derived:public Base  
    14     {  
    15     public:  
    16         virtual void mf1();  
    17         void mf3();  
    18         void mf4();  
    19         ...  
    20     };  

    在基类中,mf1() 和mf3()都被重载,子类public继承父类,这里的子类覆盖了父类中所有名为mf1和mf3的函数。因而以下调用有些会失败。

    Derived d;  
    int x;  
    ...  
    d.mf1(); // Derived::mf1  
    d.mf1(x); //错误 Derived::mf1 hiden Base::mf1  
    d.mf2();  // Base::mf2  
    d.mf3();  // Derived::mf3  
    d.mf3(x); //错误Derived::mf3 hiden Base::mf3

    由此可见,及时子类和父类内的函数有不同的参数时,子类的函数还是会覆盖所有父类中同名的函数。

    这样做的原因:避免从疏远的父类中继承重载函数。但是实际上,public继承应该遵循LSP原则,即父类和子类是Is-a 的关系,所以我们可以通过using,显示地实现对父类同名重载函数的继承。

    1 class Base{...}; //同上  
    2 class Derived:public Base{  
    3 public:  
    4     //让Base class内名为mf1与mf3的所有东西在  
    5      //Derived作用域内都可见(并且都是public)  
    6     using Base::mf1;  
    7     using Base::mf3;  
    8     ....//同上          
    9 };  
    Derived d;  
    int x;  
    ...  
    d.mf1(); //no problem. call Derived::mf1  
    d.mf1(x); //no problem. Base::mf1  
    d.mf2();  //no problem. call Base::mf2  
    d.mf3();  //no problem. call Derived::mf3  
    d.mf3(x); //no problem. Base::mf3  

    如果你不想继承所有的重载函数,则你不应该使用public继承,因为这样会违反LSP原则,你可以使用private继承,为了选择性的继承重载函数,可以使用inline 转交函数(forwarding function),具体实现如下:

     1 class Base  
     2 {  
     3 public:  
     4     virtual void mf1() = 0;  
     5     virtual void mf1(int);  
     6     ... //same as above  
     7 };  
     8 class Derived:private Base  
     9 {  
    10 public:  
    11     virtual void mf1()//转交函数(forwarding function)  
    12     {  
    13         Base::mf1();   
    14     }  
    15     ...  
    16 };  
    17 ...  
    18 Derived d;  
    19 int x;  
    20 d.mf1(); //good! call Derived::mf1  
    21 d.mf1(x); //Error as suppose,Base::mf1() was hidden.  

    关键:

      子类内的名称会遮掩父类内的名称,在pubilc继承下,不应该这样做。

      为了使被遮掩的名称可见,使用using声明或者转交函数。

  • 相关阅读:
    addClass 函数
    Javascript 严格模式详解
    Animated Scroll to Top
    Cross-Browser HTML5 Placeholder Text
    不要滥用div,保持代码的整洁
    Revit二次开发示例:DeleteDimensions
    Revit二次开发示例:ChangesMonitor
    IEnumerable,ICollection,IList,List之间的区别
    Revit二次开发示例:CancelSave
    Revit二次开发示例:AutoUpdate
  • 原文地址:https://www.cnblogs.com/bigbigtree/p/3965257.html
Copyright © 2011-2022 走看看