C++进阶--多继承

时间:2023-03-09 18:01:05
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. 在使用多继承时只从纯虚类派生
*/