Effective C++ Item 40 明智而审慎地使用多重继承

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie

经验:多重继承比单一继承复杂。它可能导致新的歧义性,以及对 virtual 继承的须要

演示样例:

class BorrowableItem{
public:
	void checkOut();
};
class ElectronicGadget{
private:
	bool checkOut() const;
};
class MP3Player:
	public BorrowableItem
	public ElectronicGadget
{...};
MP3Player mp;
mp.checkOut()

解析:找出最佳函数后才检验其可取用性。此例中对 checkOut 的调用是歧义的,即使两个函数中仅仅有一个是可取用的(一个 public , 一个 private)

纠正:明白说明调用的是哪一个 base class 内的函数

mp.BorrowableItem::checkOut();

经验: virtual 继承会添加?大小、速度、初始化(及赋值)复杂度等等成本。假设  virtual base classes 不带不论什么数据,将是最具有用价值的情况

经验:多重继承的确有正当用途。当中一个情节涉及“public 继承某个 Interface class”和"private继承某个协助实现的 class"的两相组合。

演示样例:

class IPerson{ //提供接口
public:
	static std::tr1::shared_ptr<Person> makePerson(DatabaseID personIdentifier);
	virtual ~IPerson();
	virtual std::string name() const = 0;
	virtual std::string birthDate() const = 0;
};

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;
	//...
};

class CPerson: public Iperson, private PersonInfo{
public:
	explicit CPerson(DatabaseID pid): PersonInfo(pid){}
	virtual std::string name() const{
		return PersonInfo::theName(); //利用 PersonInfo 的方法实现 IPerson 的接口
	}
	virtual std::string birthDate() const{
		return PersonInfo::theBirthDate();
	}
private:
	const char *valueDelimOpen() const {return "";} //又一次定义继承而来的 virtual "界限函数"
	const char *valueDelimClose() const {return "";}
}

DatabaseID askUserForDatabaseID();

DatabaseID id(askUserForDatabaseID());
std::tr1::shared_ptr<IPerson> pp(makePerson(id));
时间: 2024-11-05 18:42:50

Effective C++ Item 40 明智而审慎地使用多重继承的相关文章

Effective C++ Item 39 明智而审慎地使用 private 继承

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 经验:private 继承意味 is-implemented-in-terms of.它通常比 composition 的级别低. 但是当 derived class 需要访问 protected base class 的成员,或需要重新定义继承而来的 virtual 函数时,这么设计是合理的 经验:和 composition 不同, private 继承可以造成 empty base 最

Effective C++ 条款40 明确而审慎地使用多重继承

1. 使用多重继承,派生类有可能从一个以上的基类继承相同名称,这回导致歧义.即使来自不同基类的相同名称各自的访问级别不同,也有仍然有可能造成歧义,因为C++的名称查找法则是先查找最佳匹配,然后再检查可取用性.可以使用作用域操作符明确指定所使用的名字属于那一个类. 2. 如果多重继承继承的一个以上基类又出现继承自同一个类的情况,将会导致"钻石型继承",即A->B;A->C;B,C->D,此时就要面对是否将A设为虚基类的选择.如果不采用虚继承,那么A在D中会存在两份实体(

Effective C++:条款40:明智而审慎地使用多重继承

(一) 慎用多重继承,因为那样的话可能会造成歧义.. <pre name="code" class="cpp">class BorrowableItem { public: void checkOut(); }; class ElectronicGadet { private: bool checkOut() const; }; class MP3Player : public BorrowableItem <pre name="code

Effective C++ -----条款40:明智而审慎地使用多重继承

多重继承比单一继承复杂.它可能导致新的歧义性,以及对virtual继承的需要. virtual继承会增加大小.速度.初始化(及赋值)复杂度等等成本.如果virtual base classes不带任何数据,将是最具实用价值的情况. 多重继承的确有正当用途.其中一个情节涉及“public继承某个Interface class"和”private继承某个协助实现的class“的两相组合.

Effective JavaScript Item 40 避免继承标准类型

本系列作为Effective JavaScript的读书笔记. ECMAScript标准库不大,但是提供了一些重要的类型如Array,Function和Date.在一些场合下,你也许会考虑继承其中的某个类型来实现特定的功能,但是这种做法并不被鼓励. 比如为了操作一个目录,可以让目录类型继承Array类型如下: function Dir(path, entries) { this.path = path; for (var i = 0, n = entries.length; i < n; i++

Effective C++ 条款39 明智而审慎地使用private继承

1. public继承表明is-a的关系,要求接口的完全继承,而private继承表明"根据某物实现出的关系",要求仅仅继承实现,private继承有两个规则: 1). 经由private继承而来的基类的所有成员在派生类中都会变成private属性 2). 由于1),编译器不允许将派生类转为基类以防止对派生类private成员的非法访问. 2. 由条款38,private继承和复合具有相同作用——"根据某物实现出".两者之间,要尽可能使用复合,除非必要情况.必要情况

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

多重继承(multiple inheritance:MI)在C++阵营中有不同主张.一个是:如果认为单一继承(single inheritance:SI)是好的,那么多重继承一定也是好的:另一个是:单一继承是好的,但是多重继承不是.本条款主要让大家了解这两个观点. 当使用MI时,程序可能从一个以上base classes继承相同名称(函数.typedef等),这会导致歧义(ambiguity) clas BorrowableItem{ public: void checkOut(); -- };

Effective C++ Item 31 降低文件间编译依存关系

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 经验:支持"编译依存性最小化"的一般构想是:相依于声明式,不要相依于定义式. 基于此构想的两个手段是 Handle classes 和 Interface classes. 示例:相依于定义式 #include <string> #include "date.h" #include "address.h" class Perso

Effective C++ Item 3 尽可能使用const

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie const 出现在*左边指const data,出现在*右边指const pointer char greeting[] = "Hello"; char *p = greeting; //non-const pointer, non-const data const char *p = greeting; //non-const pointer, const data char