代码复用
面向对象编程的主要目的之一是提供可重用的代码。 -------- C++ Primer Plus
一、单继承
1、类继承的好处
- 可以在已有类的基础上添加功能;
- 可以给类添加数据;
- 可以修改类方法的行为;
2、派生类和基类
2.1、派生类特征
- 派生类对象中存储了基类的数据成员(派生类继承了基类的实现);
- 派生类对象可以使用基类的方法(派生类继承了基类的接口);
- 派生类需要自己的构造函数和析构函数;
- 派生类可以根据需要添加自己的方法和数据成员;
- 派生类不能直接访问基类的私有数据,而必须使用基类的公有方法才可以。派生类构造函数使用的是成员初始化列表,而其他成员函数使用的是另一种技术。
2.2、派生类的构造函数
创建派生类对象时会先创建基类对象,所以在进入派生类构造函数之前需要创建基类对象,C++使用的是成员初始化列表。
2.3、派生类和基类的特殊关系
- 派生类对象可以使用基类对象;
- 基类指针可以在不进行显式类型转换的情况下指向派生类对象;
- 基类引用可以在不进行显式类型转换的情况下引用派生类对象;
- 可以将基类对象初始化为派生类对象,此时使用的是隐式复制构造函数;
- 可以将派生类对象赋值给基类对象,此时使用的是隐式赋值运算函数;
3、多态
3.1、公有继承(is - a)
公有继承是最常用的继承方式,它建立一种 is - a 的关系,即派生类对象也是基类的一个对象,可以对基类执行的任何操作也可以对派生类执行。
3.2、多态公有继承
3.2.1、为什么使用多态
希望派生类和基类中同一个方法(跟函数的重载不同)的行为不同,即方法的行为应该取决于该方法的对象。
3.2.2、实现机制
- 在派生类中重新定义基类的方法;
- 使用虚方法
- 在方法声明前加
virtual
,即可将方法声明为虚方法; - 虚方法的作用是:如果方法是通过引用或指针而不是对象来调用的,他将决定使用哪一种方法。如果没有
virtual
,程序将根据引用或指针类型选择方法;若使用virtual
,则根据引用或指针指向的对象类型来选择方法。
- 在方法声明前加
3.2.3、注意
- 在派生类中使用基类方法的标准技术是使用作用域解析算符。
- 经常在基类中将派生类会重新定义的方法声明为虚方法,方法在基类中被声明为虚后,它在派生类中将自动成为虚方法,可以加
virtual
; - 虚析构函数;
4、抽象基类(Abstract base class)
4.1、为什么要用ABC
两个类之间不是 is - a 的关系,直接继承不太理想;但二者之间又有一些共同的特征,分别定义效率不高;这时,我们可以将二者的共性抽离出来形成一个共同的基类,再分别派生。
4.2、机制
- 纯虚函数(pure virtual function):再相应的函数声明后加
=0
;
4.3、说明
- 为什么说这个共同的基类是抽象的:这个基类有派生类的共性,比如一个方法,但是派生类实现这个方法的方式可能不一样,因此,基类中的该方法不应有函数体,只是提供一个接口。
- 要想成为抽象基类,必须包含纯虚函数;不能创建抽象基类的对象,但能创建引用和指针。
二、包含
1、包含(has - a)
- 本身是另一个类的成员。
1.1、初始化
- C++要求在构建对象的其他部分之前,先构建继承对象的所有成员对象。
- 初始化的是成员对象,不是继承对象,所以初始化列表中使用的是成员名,而不是类名。
2、私有继承(has - a)
- 使用私有继承,基类的公有成员和保护成员都将成为派生类的私有成员。
- 语法和公有继承类似,功能和包含类似。
2.1、初始化
- 使用初始化列表的方式来初始化继承对象,初始化列表使用的是类名。
2.2、注意
- 包含将对象作为一个命名的成员对象添加到类中,而私有继承将对象作为一个未被命名的继承对象添加到类中。
- 在私有继承中,未进行显式类型转换的派生类引用或指针,无法赋值给基类的引用或指针。
三、多重继承(MI)
- MI描述的是有多个直接基类的类,与单继承一样,公有MI表示的也是 is - a 关系。
1、问题
- 从两个不同的基类继承同名的方法;
- 从两个或更多相关基类处继承同一个类的多个实例;
2、机制
- 上述两个问题的根源是:派生类对象中有两个间接基类对象的拷贝,这不合理。
- 引入虚基类;
3、虚基类
3.1、构造函数
- C++在基类是虚时,禁止信息通过中间类自动传递给基类;编译器必须在构造派生对象之前构造基类对象组件;使用成员初始化列表来初始化。
- 必须显式的调用间接基类的构造函数,否则会自动调用默认构造函数。
3.2、成员函数
- 多重继承可能导致函数调用的二义性。
- 可采用模块化编程的思想来解决这个问题。
3.3、支配
- 使用虚基类将改变C++解析二义性的方式。使用非虚基类时,如果类从不同的类那里继承了两个或多个的同名成员时,则使用该成员名时,如果没有用类名进行限制,将导致二义性。但如果使用的的虚基类,则不一定会导致二义性。
- 如果某个名称优先于(dominates)其他所有名称,则使用它时,即使不使用限定符,也不会导致二义性。
- 支配:派生类中的名称优先于直接或间接祖先类中相同的名称;
- 虚二义性规则(支配规则)和访问规则无关。
原文链接: https://www.cnblogs.com/xxiaobai/p/12659473.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;
也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/340635
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!