600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > 【Effection C++】读书笔记 条款40:明智而审慎的使用多重继承

【Effection C++】读书笔记 条款40:明智而审慎的使用多重继承

时间:2023-08-24 10:51:05

相关推荐

【Effection C++】读书笔记 条款40:明智而审慎的使用多重继承

【Effection C++】继承与面向对象设计

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

首先介绍一个个小知识,在C++解析一个名称的时候,首先是名字查找(涉及到作用域),然后是类型匹配,从中找到最佳匹配,最后是检查可用性(private,protected,public等)。

1. 多重继承比单一继承要复杂,它很有可能导致歧义。

示例如下:

class Base1{public:void fun(){}};class Base2{private:void fun(){}};class Derived : public Base1, public Base2{};int main(){Derived d;d.fun(); //错误:对fun的调用有歧义return 0;}

这个例子展现两个知识点:

多重继承的情况下,很容易造成名字的歧义,使得我们对类的维护增加了困难。解析函数调用时候,先名字查找,然后寻找最佳类型匹配,最后判断可用性。因为Base1和Base2中的fun的fun的匹配度一样好,就会直接抛出错误,而不是等到下一步。

改进方法,可以在Derived内显示声明需要调用的函数

class Derived : public Base1, public Base2{public:void fun(){Base1::fun(); //显示声明消除歧义} };int main(){Derived d;d.fun(); //OKreturn 0;}

2. virtual继承及其带来的复杂性

多重继承除了可能导致更多的歧义以外,还需要注意到的就是是否需要虚继承。

考虑这样一种情况,对于基类A,类B和类C都继承于A,类D又同时继承了B和C(多重继承),那么在类D中是应该具有一份A还是两份A呢?

class A{};classs B:public A //B中有一份A{};classs C:public A //C中有一份A{};classs D:public B,public C //D中有份A{};

对于C++而言,默认的情况就是D中存在这两份A,但是,在实际生活中,经验往往告诉我们一个D中只有一份A。

但如果在继承的时候加了采用虚继承的方式,像下面这样:

class B: virtual public A{…}class C: virtual pulibc A{…}

那么D中就只有一份A了。

虚继承的要求在于,所有直接继承自基类的classes都采用“virtual 继承”的方式,这样子再对这些类进行多重继承的时候,就会在最底层的派生类中只有一份基类了。

C++标准库里面的流就是采用这样的形式,有一个父流basic_ios,basic_istream和basic_ostream分别虚继承于basic_ios,而basic_iostream又多重继承于basic_istream和basic_ostream。

从正确行为的观点来看,public继承几乎总应该是virtual的。但是为了支持virtual,编译器必须做更多幕后工作,由此而来带来的后果就是:

使用virtual继承的那些classes所产生的对象往往比使用non-virtual继承的兄弟们体积大,访问virtual base classes的成员变量时,也比访问non-virtual base classes的成员变量速度慢。除此之外,virtual base的初始化职责是由继承体系中的最底层class负责。

所以作者对于virtual base classes的忠告是:

非必要不使用virtual classes继承,平常请使用non-virtual classes继承

如果必须使用virtual base classes,尽可能避免在其中放置数据。这样子可以不用担心其初始化和赋值操作。

3. 多重继承的确有正当用途

多重继承有其复杂性,但是在一定情况下也是有着其的用途的。在Effective C++一文中就提出了一个例子,主要就是“public继承某个Interface class” 和 “private 继承某个协助实现的class”的两相组合。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。