• C++进阶--多继承


    //###########################################################################
    /*
     * 多继承
     *
     *  -- 一个类直接派生自不止一个基类
     *
     *  -- 利弊?
     */
    
    
    //###########################################################################
    /*
     * 多继承
     */
    
    
    class InputFile {
       public:
       void read();
       private:
       void open();
    };
    
    class OutputFile {
       public:
       void write();
       void open();
    };
    
    class IOFile : public InputFile, public OutputFile {
    };
    
    int main() {
       IOFile f;
    }
    
    
    // Notes:
    //   void open();
    //   f.open();    //这里编译不过,即使其中一个是私有函数。因为函数匹配性检查在权限检查之前
    //正确的调用方式:
    //f.Output::open();
    //两者类都存在open函数,改进成如下方式
    
    
    class File {                //         File
       public:                  //         /          -
       string name;        // InputFile  OutputFile
       void open();           //           /
    };                            //        IOFile
    
    class InputFile : virtual public File {
    };                              
                                    
    class OutputFile : virtual public File {
    };                              
    
    class IOFile : public InputFile, public OutputFile {
    };  // 菱形继承
    
    int main() {
       IOFile f;
       f.open();    //但是这样仍然编译不过,open()二义性
       //f.InputFile::name = "File1";  //不仅open有两个,name也有两个
       //f.OutputFile::name = "File2";
    }
    
    
    //解决方式: 虚继承
    //但是引入了一个新问题,基类的初始化用哪个?
    //C++提供了在最终派生指定的一个解决办法
    class File {     
       public:      
       File(string fname);
    };             
    
    class InputFile : virtual public File {
       InputFile(string fname) : File(fname) {}     //这边的File(fname)会被忽略
    };                              
                                    
    class OutputFile : virtual public File {
       OutputFile(string fname) : File(fname) {}    //这边的File(fname)会被忽略
    };                              
    
    class IOFile : public InputFile, public OutputFile {
       IOFile(string fname) : OutputFile(fname), InputFile(fname), File(fname) {} //不管派生类有多远,都要负责初始化虚基类
    };  
    
    int main() {
       IOFile f;
    }
    
    
    // 既然有这些问题,为什么要用多继承?
    /*
     * 接口隔离原则
     * 
     * 将大的接口分割成更小且更专用的接口。从而使用户只需要知道他们感兴趣的方法
     */
    
    //例如,Andy可能总共有500个API,但是如果你只关心他作为工程师的特性,你只需要知道工程师的40个API
    class Engineer {
       public:
       ...; // 40 APIs
    };
    
    class Son {
       public:
       ...; // 50 APIs
    };
    
    ...
    
    class Andy : public Engineer, Son {
       public:
       ...; // 500 APIs
       };
    
    
    /*
     * ISP的好处:
     * 1. 接口易于使用
     * 2. 静态类型安全
     */
    /*
    
    // 那么怎么样在享受多继承的好处的同时,避免前面提到的问题
     *  【纯虚类】
     *
     *  虚类: 有一个或多个纯虚函数的类
     *
     *  纯虚类: 
     *  一个类只包含纯虚函数
     *    - 没有数据
     *    - 没有实体函数
     *    - 没有私有和保护的函数
     */
    
    class OutputFile {
       public:
       void write() = 0; //没有初始化及二义性的问题
       void open() = 0;
    };
    
    
    
    /*
     * 总结:
     * 1. 多继承是一个重要的技术, 即 接口隔离原则
     * 2. 在使用多继承时只从纯虚类派生
     */
    
  • 相关阅读:
    一些业内有名的网站收集
    WCF重载
    FCKEditor fckconfig.js配置,添加字体和大小 附:中文字体乱码问题解决
    查询第几条到第几条的数据的SQL语句
    SPOJ 9939 Eliminate the Conflict
    UVA 10534 Wavio Sequence
    HDU 3474 Necklace
    POJ 2823 Sliding Window
    UVA 437 The Tower of Babylon
    UVA 825 Walking on the Safe Side
  • 原文地址:https://www.cnblogs.com/logchen/p/10176786.html
Copyright © 2020-2023  润新知