C++進階--多繼承
阿新 • • 發佈:2018-12-25
//########################################################################### /* * 多繼承 * * -- 一個類直接派生自不止一個基類 * * -- 利弊? */ //########################################################################### /* * 多繼承 */ 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. 在使用多繼承時只從純虛類派生 */