c++公有继承、私有继承和复合

本文详细介绍了C++中继承的概念,包括公有继承、私有继承和复合。公有继承实现了"is-a"关系,但需要注意避免覆盖继承得到的名字,以及正确使用虚函数。私有继承则意味着"is-implemented-in-terms-of",常用于实现细节。复合用于"has-a"和"is-implemented-in-terms-of"关系。同时,文章讨论了多继承的问题和应用场景。
摘要由CSDN通过智能技术生成

effective c++ Item32~40 学习整理

概括:

Item 32 介绍了public inheritance 公有继承实现"is-a"关系。Item 33-Item 36介绍public inheritance使用中需要注意的地方。其中,Item 33 告诫不论non-virtual,virtual/pure-virtual 都应该避免覆盖;Item 34、35、37 告诫virtual的使用需要注意的地方,35还提供了虚函数virtual替代方案;Item 36 告诫non-virtual 不要当作virtual使用。
Item 38、39 介绍了public inheritance场景以外其他场合该用的情形:复合,实现 ”has-a”、”is-implemented-in-terms-of”关系。Item 39 介绍了private 继承,提供了另一种实现“is-imlemented-in-terms-of”关系的方法。
Item 40 介绍了多重继承存在的问题和适用的场景

详细来看:

Item 32 介绍public inheritance(公有继承)的概念

(1)概念:在B适用的同样D也适用,D就可以从B 公有继承过来。public inheritance 意味着"is-a"。适用于base classes 的每一件事也适用于derived classes,因为derived class object都是一个 base class object。例如:学生和“人”的关系。
在这里插入图片描述
(2)公有继承的双方的一个性质:c++领域中,任何期望引用类型为Person的函数,都可以接受一个Student对象,反之不成立。
在这里插入图片描述
(3)作者在类的设计上的观点:“没有一个适用于所有软件的完美设计”、“最好的设计依赖于系统究竟期望做什么,无论现在还是未来”。

Item 33 : 避免覆盖通过继承得到的名字。

这里的原因和继承没有关系,属于c++作用域范畴。该Item告诉我们D(derived class)中的名字会覆盖B(base class)中的名字,这从来不是我们想要的。如下面的例子,D(derived class)进行了覆盖。B(Base class)中的mf1和mf3被D(derived class)中的mf1和mf3覆盖。
在这里插入图片描述
这么操作会带来吃惊的意外:
在这里插入图片描述

Base class中的所有名为mf1和mf3的函数被Derived class中的mf1和mf3覆盖。但实际上我们是需要继承Base class中的overloads的。
在这里插入图片描述
解决办法是:使用using declarition 或者 forward function,这里effective c++作者提供了一个绕过“c++”对“通过继承得到的名字”的缺省覆盖机制:如果base class 对成员函数有重载的话,derived class 需要为每一个不想覆盖的名字使用using declarition, 否则,一些希望继承下来的名字会被覆盖。
在这里插入图片描述
在这里插入图片描述
注:作者为说明举例 mf3不是个好例子,mf3本身就不该在Derived class里重新定义。mf1更有警示价值。

Item 34:继承分接口继承,实现继承和both(两者都继承)。

在考虑基类的设计时,对每个成员函数,我们该声明成哪一类,这样可以精确指定我们需要派生类继承什么东西,而不是统一随意的都声明为non-virtual或者都为virtual类型。

(1)这3类声明的介绍:

(1.1)声明一个纯虚函数pure virtual的目的是使 类D(derived class)仅仅继承一个函数的接口,适用于派生类对该接口的实现都不同的情形。如果非要给纯虚函数提供定义也可以,调用的时候需要用class name限定修饰这个调用(几乎没人这么用)。
(1.2)声明一个虚函数virtual的目的与纯虚函数不同,其目的是类D(derived class)既继承类B(base class)的接口,也继承一个来自类B(base class)的实现,该实现作为类D的缺省实现存在。
(1.3)声明一个非虚成员函数non-virtual,使类D(derived class)既继承接口,又继承实现,且该实现不会改变。

(2)虚函数virtual的风险点和规避办法:

(2.1)风险点:类D(derived class) 如果忘记改写实现,这时类B(base class)提供的缺省行为又不是我们想要的,那么实际的行为会与预期不符!
(2.2)规避办法:切断虚拟函数的接口和它的缺省实现之间的联系。“为derived class提供缺省行为,但是除非他们提出明确的要求,否则就不交给他们”可以很容易做到,从而达到规避缺省继承带来的问题。具体的实施方案如下:
方法1:说白了就是利用”pure virtual 接口必须实现”的规定,再将缺省实现放到类B(base class)的另一个独立的成员函数中,让这个成员函数非虚non-virtual。如下:
原来的B-D &

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值