Effective C++ 条款40

条款40 明智而审慎地使用多重继承

多重继承的意思是继承一个以上的base classes,但这些base classes并不常在继承体系中又有更高级的base classes。举例如下,


class File{};
class InputFile:public File{};
class OutFile:public File{};
class IOFile:public InputFile,
	public OutFile{};

上述继承体系中,File与IOFile之间有一条以上的相通路线。于是IOFile继承File成员时,需要面对的问题:是打算让base class内的成员变量经由每一条路径被复制(成员变量重复啦),还是说IOFile从InFile和OutFile继承的成员变量(其继承来自File)不该重复?

两个阵营,而C++在此表示中立(都可以哈)。于是引出虚基类的概念,即防止同一基类成员因不同相通路线而被复制多次。当然,虚继承是要付出相应代码代价的哈!


具体做法如下,

class File {};
class InputFile :virtual public File {};
class OutFile :virtual public File {};
class IOFile :public InputFile,
	public OutFile {};
作者对virtual base classes的忠告:i、非必要不使用virtual bases。平常请使用non-virtual继承。ii、如果必须使用virtual base classes,尽可能避免在其中放置数据。这样就不需担心classes身上的初始化(和赋值)所带来的诡异事情。


以下举例实现一个public和private并存的多重继承,public继承是is-a关系,而private继承是is implement in terms of关系,具体举例见下代码,

class DatabaseID{};
class IPerson {//抽象基类
public:
	virtual ~IPerson();
	virtual string name()const = 0;
	virtual string birthDate()const = 0;
};

/*中间block没太看懂想表达的意思
//factory function,根据一个独一无二的数据库ID创建一个Person对象
std::tr1::shared_ptr<IPerson> makePerson(DatabaseID personIdentifier);

DatabaseID askUserForDatabaseID();//这个函数从使用者手上取得一个数据库ID

DatabaseID id(askUserForDatabaseID());
std::tr1::shared_ptr<IPerson> pp(makePerson(id));//创建一个对象支持Iperson接口,
                                                 //借由Iperson成员函数处理*pp
*/

//与数据库相关的class,名为PersonInfo,提供Cperson所需要的实质东西:
class PersonInfo {
public:
	explicit PersonInfo(DatabaseID pid);
	virtual ~PersonInfo();
	virtual const char* theName()const;
	virtual const char* theBirthDate()const;
	virtual const char* valueDelimOpen()const;
	virtual const char* valueDelimClose()const;
	...
};

于是下面所要给出的CPerson和PersonInfo的关系是,PersonInfo刚好有若干函数可帮助CPerson比较容易实现出来,而IPerson则提供给CPerson接口,运用多重继承,完美哈!


class Cperson :public IPerson, private PersonInfo {
public:
	explicit Cperson(DatabaseID pid):PersonInfo(pid){}
	virtual string name()const {
		return PersonInfo::theName();//实现必要的IPerson成员函数
	}
	virtual string birthDate()const {
		return PersonInfo::theBirthDate();//实现必要的IPerson成员函数
	}
private:
	const char* valueDelimOpen()const { return ""; }//重新定义继承而来的virtual"界限函数"
	const char* valueDelimClose()const { return ""; }
};


以上内容均来自Scott Meyers大师所著Effective C++ version3,如有错误地方,欢迎指正!相互学习,促进!!

猜你喜欢

转载自blog.csdn.net/tt_love9527/article/details/80834380