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

    1、C++的名称遮掩规则

    名称遮掩规则做的事就是:遮掩名称。

    • 假如这个名称是一个变量,那么无论这两个变量的类型是否相同,都会被遮掩。
    • 假如这个名称是一个函数,那么无论函数的参数有几个,无论这个同名的函数有几个重载的版本,这些函数全都会被遮掩。

    2、派生类的成员函数内查找名称的顺序

    • 先在成员函数体内查找(local作用域)。
    • 找不到的情况下,在派生类内查找。
    • 找不到的情况下,在派生类所继承的基类内查找。
    • 找不到的情况下,在派生类所属namespace查找。
    • 找不到的情况下,在global作用域查找。
    • 找不到的情况下,则会报错。

    3、名称遮掩与继承

    情况一:
    在这里插入图片描述
    派生类mf1() 覆盖基类mf1(),此时基类中并没有重载的mf1()函数。在这样的情况下,一切运作正常。
    情况二:
    在这里插入图片描述
    基类中,mf1()和mf3()有重载的版本,此时在派生类中修改mf1()、mf3()时,修改的那本版本的函数正常运作,没被修改的版本的成员函数被遮盖。此时,实际上就违背了public继承的is-a关系。因此应该避免这种情况。

    4、如何解决上述名称遮掩问题?

    方案一:

    • 给需可能被遮掩的名称:加using 基类名称声明。放在派生类定义的public作用域中。

    方案二:

    如果编译器不支持using声明,public继承的名称遮掩问题也可以用转交函数实现。
    即:为每一个基类版本写转交函数。

    5、private继承和public继承与名称遮掩

    • public继承派生类不能只继承一部分成员,必须要全部继承。即:塑模is-a关系。
    • private继承可以继承一部分成员。此时使用转交函数技术实现这一需求。

    使用转交函数实现部分继承:

    class Base { 
    private: 
        int x; 
    public: 
        virtual void mf1() = 0; 
        virtual void mf1(int); 
        virtual void mf2(); 
        void mf3(); 
        void mf3(double); 
    };
     
    class Derived : private Base { 
    public: 
        virtual void mf1()//转交函数 
        { 
            Base::mf1();//暗自转成inline 
        }
    };
     
    Derived d; 
    int x; 
    d.mf1();//调用的是Derived::mf1 
    d.mf1(x);//错误,Base::mf1()被遮掩了
    

    在这里转交函数做到了两点:

    • 转交函数内部调用基类的mf1()无参函数,因此实现了继承基类的无参mf1()
    • 而同时由于mf1遮掩了基类的mf1(),因此其他版本的mf1()在该private继承的派生类中是不可见的。

    这便实现了只继承基类的一部分。

  • 相关阅读:
    Git:创建远程仓库并推送内容到远程库
    Git中ssh的使用
    Git中的文件上传、修改、撤消修改和删除
    Git的安装和创建版本库
    HTML相关知识点总结
    Android开发--TableLayout的应用
    Java中sql语句的引号问题
    NXOPEN环境配置
    shell小技巧
    查询MySQL锁等待的语句
  • 原文地址:https://www.cnblogs.com/lasnitch/p/12764194.html
Copyright © 2011-2022 走看看