条款40:慎重的选择多重继承

多重继承很容易带来的一个问题就是歧义的问题:

 1 class BorrowAble{
 2 public:
 3     void checkOut() const;
 4     ...
 5 };
 6 class ElectronicGadget{
 7 private:
 8     bool checkOut()const;
 9     ...
10 };
11 class MP3Player:
12     public BorrowAbleItem,
13     public ElectronicGadget
14     {...};
15 MP3Player mp;
16 mp.checkOut();

这样checkOut的调用实际上就是未定义的了,不考虑作用域来说,这个mp能够取得两个checkOut的名称。

可能的调用方法就是:mp.BorrowableItem::checkOut();

还有一种致命的问题就是:如果两个base类还拥有一个相同的基类的话,那么就会导致base对象的重复发生。正确的做法是像下面这样使用virtual继承,这样就避免了继承相同的数据:

1 class File{...};
2 class InputFile : virtual public File{...};
3 class OutputFile : virtual public File{...};
4 class IOFile : public InputFile,
5                 public OutputFile
6                 {...};

当然,使用virtual继承是要付出代价的,起生成的对象往往会更大以及访问速度也会变慢。

另外一个不太显著的缺点是,通过virtual继承得到的最终类往往与其含有数据的基类距离不止一个的继承距离。但是这些类同时还要负责这些佛如初始化工作。

所以综上所述:对于virtual base class 的忠告是很简单的:非必须不要使用virtual base, 如果要使用尽量不要再virtual base中存放数据,以免忘了进行初始化工作之后带来一些诡异的后果。

小结:

多重继承比单一继承要复杂,可能会导致新的歧义性,以及起往往还需要virtual继承

virtual继承会增加,大小,速度,初始化,复杂度等成本,最好的virtual base class不应该带有数据。

多重继承的正确用途往往出现在:

pubic继承自某个interface class以及private 继承字某个协助实现的class二者的组合。

时间: 2024-10-26 15:50:39

条款40:慎重的选择多重继承的相关文章

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 STL 条款1:仔细选择你的容器

条款1:仔细选择你的容器 了解各种容器的实现方法,知道各种容器的内存管理方式.各种操作所对应的底层操作,然后根据需要选择恰当的容器. 对于容器的分类: 标准STL序列容器:vector,string,deque和list 标准STL关联容器:set,multiset,map和multimap 非标准序列容器:slist(单向链表)和rope(重型字符串--不懂) 非标准关联容器:hash_set,hash_multiset,hush_map和hash_multimap vector == str

慎重别选择到&quot;僵尸&quot;软件

何谓僵尸? 没有灵魂,动作单一,我们电视电影上经常看见, 只能往前跳,不会走路, 手向前伸直,左右摆攻击. 何谓"僵尸"软件? 根据僵尸的特性,大概有如下几类: 1.没有任何创新性,直接把别人的软件抄一下,到底为什么这样设计都不知道,有些功能只抄了个表面,内涵一点没有. 这种我们认为是没有"灵魂"的软件. 2.半年没有更新,甚至一年几年没更新的软件, 为什么软件没更新, 有些用户说,这软件很完善很稳定了,所以没有更新的必要了. 我不想总拿微软来说事,但没办法,操作系

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

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

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

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

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

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

Effective C++条款40

本节条款讲述了多重继承的使用 多重继承一般情况下用的很少,原因在于多重继承容易出现程序错误.以下去两个典型的调用错误: 第一种错误如下代码: #include<iostream> using namespace std; class B { public: virtual int m(){} }; class C { public: virtual int m(){}; }; class D :public B,private C { public: }; int main() { D d;

ISO/IEC 9899:2011 条款6.8.4——选择语句

6.8.4 选择语句 语法 1.selection-statement: if    (    expression    )    statement if    (    expression    )    statement    else    statement switch    (    expression    )    statement 语义 2.一条选择语句在一组语句中选择,依赖于一条控制表达式的值. 3.一条选择语句是一个语句块,其作用域是其封闭语句块的一个严格的子集

effective c++条款32~40“继承与面向对象设计”整理

条款32:确定你的public继承塑模出is-a关系 以C++进行面向对象编程,最重要的一个规则是:public inheritance(公有继承)意味is-a(是一种)的关系. 在C++领域中,任何函数如果期望获得一个类型为基类的实参(而不管是传指针或是引用),都也愿意接受一个派生类对象(而不管是传指针或是引用).(只对public继承才成立.)好的接口可以防止无效的代码通过编译,因此你应该宁可采取"在编译期拒绝"的设计,而不是"运行期才侦测"的设计.is a并不