GeekBand-secondweek-c++的组合和继承

组合与继承

c++最重要的特性之一就是对代码的重用,除了拷贝,c++应该具有更深入的功能

1、组合和继承

组合是简单地创建一个包含已存在的类对象的新类,新类是由已存在的类对象组合而成的;继承是以一个已存在类为基础创建一个新类,增加或重写成员函数,增加成员变量,但不缩减它的内容,称为继承;

组合与一般的类区别不大,只是成员变量有部分对象,而不是一味的内置类型。

2、简单继承

最简单的继承,无任何虚函数,基类与派生类无任何相同名字的成员变量和成员函数,public派生时,对函数的使用就按照名字来,但是当派生类重定义了与基类相同的成员变量或函数时,使用基类的函数要按照(基类名::函数或基类名::变量)的方式调用,对基类函数的重定义会把基类版本隐藏,类外不能使用基类版本。

成员重定义与名字隐藏:简单继承里,基类和派生类要看成两层,每一层内,函数可以重载,但是一旦派生类的函数重定义了基类函数(可以认为是只要用了函数名),那么基类版本的此名字的函数都被隐藏,只能通过域操作符并在派生类内进行访问;

不能继承的函数:构造函数和析构函数都是用来处理当前类的对象的,它们只对当然类有意义,所以继承时,构造函数和析构函数是不会被继承的;operator=也不能被继承;

3、构造函数初始化列表

正常情况下,编译器可以调用组合中子对象的默认构造函数来构造子对象,但如果没有默认构造函数或者需要用另一个版本的构造函数时就需要在初始化列表中完成;组合和继承的构造函数初始化列表一样,组合使用子对象名,继承使用基类名;内置类型的对象也可以放到这个初始化列表中,使用方式一样,当然它并不是调用构造函数,而是简单的赋值初始化,如果不显性初始化,这些变量不会自动初始化;

4、继承和组合的联合

组合与继承同时使用时,可以简单认为组合中的子对象是内置类型的变量,这样就可以简化看做是非联合的普通继承行为;

构造与析构:构造从类层次最根处开始,而每一层中,先构造基类,再构造子对象,其中子对象构造顺序按照类内声明的顺序而非初始化列表顺序;调用析构时,严格反向调用;

5、多重继承

上面介绍我们可以从一个已有类继承,那么我们也就应该能同时从多个类继承,实际上这是可以做到的,但是否它象设计部分一样有意义仍是一个有争议的话题。不过有一点是可以肯定的:直到我们已经很好地学会程序设计并完全理解这门语言时,我们才能试着用它。这时,我们大概会认识到,不管我们如何认为我们必须用多重继承,我们总是能通过单重继承来完成实现这样的需求。起初,多重继承似乎很简单,在继承期间,只需在基类表中增加多个类,用逗号隔开。然而,多重继承是有很多含糊的可能性;

6、继承的优点

继承是以那些已经存在的能很好运行的类为基础,丰富或者重新实现它们,这就意味着,我们可以把基类作为地基,然后在其上实现我们的建筑,如果出了问题,也可以肯定是我们本层的实现引发的错误,更全面地看,是一种层次化的递进,地基很抽象,建筑很具体;

认识到程序开发是一个渐增过程,就象人的学习过程一样,这是很重要的。我们能做尽可能多的分析,但当开始一个项目时,我们仍不可能知道所有的答案。如果开始把项目作为一个有机的、可进化的生物来“培养”,而不是完全一次性的构造它,使之像一个玻璃盒子式的摩天大楼,那么我们就会获得更大的成功和更直接的反馈。虽然继承是有用的技术,但在事情稳定之后,我们需要用新眼光重新审视一下我们的类层次,把它看成可感知的结构。记住,继承首先表示一种关系,其意为:“新类是老类的一个类型。”我们的程序不应当关心怎样摆布比特位,而应当关心如何创建和处理各类型的对象,以便用问题的术语表示模型。(没有更好的描述来总结这段话了)

7、向上映射

更深入地思考,继承不仅仅是让派生类能访问基类的成员,而是意味着派生类是一个特殊的基类,是一个特殊实例化的基类,这点很重要,这个特殊实例并不一定是基类子集,而是更具体的扩展集

7.1 向上映射:也就是一个接收基类对象的地方,可以将一个继承类的对象传递给它,向上映射是安全的,因为基类总不会比派生类缺少内容;指针和引用也支持向上映射,即基类指针或引用支持接收派生类对象的地址或引用;同样的,向下映射也是可行的,但是涉及一些问题的讨论,我们在17章说明这个问题;

引发的危机:对于隐含的类型转换,编译器只能认可形参的类型,所以函数内部对基类对象的成员函数的调用就是基类实现的版本,而无论传递的实参是什么类型对象,这显然并不是我们想要的结果。

选择组合和继承时,是否需要向上映射也是抉择哪一个的依据;

注意:简单继承中,基类函数与派生类函数都是实实在在的函数(即使派生类重定义了部分函数),所以编译器在编译时就确定了该调用哪个函数,传入的对象实参实际上是某类的数据成员部分,也就是函数最终使用的是对象的数据部分;(可以用没有虚函数表这个东西来解释简单继承所引发的向上映射的实际效果)

时间: 2024-11-10 01:16:03

GeekBand-secondweek-c++的组合和继承的相关文章

C++中组合和继承的初始化

在C++中单个类的初始化比较简单就略过不说. 当一个类继承了另外一个类,或者是一个类中还存在一个类 class A{ ... }: class B { ... }: class C:classA{ private: B bb; int x public: C(int ii):B(ii),bb(ii) ,x(ii){}; }: 此时我们进行初始化的设置采用的 C(int ii):B(ii),bb(ii), x(ii)这里必须说清楚的有几点: 1.参数是通过C(int ii)向冒号之后的类或者是变量

编写高质量代码改善C#程序的157个建议——建议103:区分组合和继承的应用场合

建议103:区分组合和继承的应用场合 继承所带来的多态性虽然是面向对象的一个重要特性,但这种特性不能在所有的场合中滥用.继承应该被当做设计架构的有用补充,而不是全部. 组合不能用于多态,但组合使用的频率却要远远高于继承. 继承UML图如下: 对应的代码如下: abstract class Stream { //省略 } class FileStream:Stream { //省略 } class MemoryStream : Stream { //省略 } 组合UML图如下: 对应代码如下: c

深入理解React组件传值(组合和继承)

在文章之前,先把这句话读三遍 Props 和组合为你提供了清晰而安全地定制组件外观和行为的灵活方式.注意:组件可以接受任意 props,包括基本数据类型,React 元素以及函数. 来源于React中文文档,组合和继承的一句话 其实这句话之前看过很多遍,主要还是应用于数据获取上. 在完全理解这句话之前,在写子组件改变兄弟子组件的状态上,没有头绪,同事上午跟我讲解了,我自己再把代码重新写一遍就认识到了,我完全忽略了组件传函数的方法,解锁这个方法以后,再写代码如同打开了一扇大门. 下面来看例子: 以

Java基础 -- 复用类(组合和继承)

复用类有两种实现方式. 在新的类中产生现有类的对象,由于新的类是由现有类的对象所组成,所以这种方法称之为组合. 采用继承实现. 一  组合语法 下面创建两个类WaterSource和SprinklerSystem.其中SprinklerSystem中包含WaterSource的对象引用. class WaterSource { //如果定义时没有初始化,则基本类型会被自动初始化为0,对象引用初始化为Null private String s; WaterSource(){ System.out.

结合使用组合和继承

虽然编译器强制你去初始化基类,并且要求要在构造器起始处就要这么做,但是它并不监督你必须将成员对象也初始化. 是这样理解的: new一个子类对象时,要调用子类的构造方法,再调用方法的首行调用父类的构造方法,如果调用无参数的,默认调用. 如果子类对象中有成员属性对象时,此属性编译器不检查此成员属性是否初始化. 版权声明:本文为博主原创文章,未经博主允许不得转载.

Java 继承、多态与类的复用

摘要: 本文结合Java的类的复用对面向对象两大特征继承和多态进行了全面的介绍. 首先,我们介绍了继承的实质和意义,并探讨了继承,组合和代理在类的复用方面的异同.紧接着,我们依据继承引入了多态.介绍了它的实现机制和详细应用.此外,为了更好地理解继承和多态.我们对final关键字进行了全面的介绍. 在此基础上.我们介绍了Java中类的载入及初始化顺序.最后.我们对面向对象设计中三个十分重要的概念–重载.覆盖与隐藏进行了详细的说明. 要点: 继承 组合,继承,代理 多态 final 关键字 类载入及

【OC学习-13】什么是组合,它和继承是什么关系?

继承有两缺点:(1)当层级越来越多时,假如每一个层级都有实例变量,那么最下层的子类继承的实例变量会超级多,沉重.(2)当消息传递自子类往上时.层级越多,效率越低下. 所以就有了组合.说实话区分继承和组合真不是那么easy.所谓两者是"is a"关系则是继承,两者是"has a"则是组合,还是模糊.事实上.这两个概念无须区分十分明显,仅仅须要记住:a)组合和继承实现的功能几乎相同,可是实现的形式不一样,记住各自的形式就可以:b)尽量用组合. 很多其它差别详见:http

java-组合优于继承

组合和继承,都能实现对类的扩展. 区别如下表所示 组合 继承 has-a关系 is-a关系 运行期决定 编译期决定 不破坏封装,整体和局部松耦合 破坏封装,子类依赖父类 支持扩展,随意增加组合类 只能继承一个父类,必须包含所有方法,增加系统复杂性 动态选择组合类方法 复用父类方法 下面通过一个例子说明,子类继承必须包含所有父类方法,增加了出错率,修改父类方法会引起所有子类功能变化. /** * 呼叫基类 * * @author peter_wang * @create-time 2014-5-2

Python学习之旅—面向对象进阶知识:类的命名空间,类的组合与继承

前言 上篇博客笔者带领大家初步梳理了Python面向对象的基础知识,本篇博客将专注于解决三个知识点:类的命名空间,类的组合以及面向对象的三大特性之一继承,一起跟随笔者老看看今天的内容吧. 1.类的命名空间 在上一篇博客中,我们提到过对象可以动态添加属性,一起来回忆下昨天的知识点,看如下的代码: class A: pass a = A() a.name = 'alex' print(a.name) 这里我们手动为a对象添加了一个属性name,然后直接打印可以得到a对象的名称.通过这个例子,我们可以