您的位置:首页 > 编程语言 > C语言/C++

【C++学习历程6】继承和派生

2018-01-15 21:00 330 查看
什么是继承

1、类之间的关系

包含关系 has-A

使用关系 use-A

继承关系 is-A

继承(Inheritance)可以理解为一个类从另一个类获取成员变量和成员函数的过程。例如类 B 继承于类 A,那么 B 就拥有 A 的成员变量和成员函数。被继承的类称为父类或基类,继承的类称为子类或派生类。

派生类除了拥有基类的成员,还可以定义自己的新成员,以增强类的功能。

以下是两种典型的使用继承的场景:

1) 当你创建的新类与现有的类相似,只是多出若干成员变量或成员函数时,可以使用继承,这样不但会减少代码量,而且新类会拥有基类的所有功能。

2) 当你需要创建多个类,它们拥有很多相似的成员变量或成员函数时,也可以使用继承。可以将这些类的共同成员提取出来,定义为基类,然后从基类继承,既可以节省代码,也方便后续修改成员。

定义与性质

定义:

class 派生类名: 继承方式 基类名

{

派生类新增成员的声明;

}

性质:

1、子类拥有父类的所有成员变量和成员函数

2、子类可以拥有父类没有的方法和属性

3、子类就是一种特殊的父类

4、子类对象可以当作父类对象使用

继承的访问控制

不同的继承方式会影响基类成员在派生类中的访问权限。

1) public继承方式

基类中所有 public 成员在派生类中为 public 属性;

基类中所有 protected 成员在派生类中为 protected 属性;

基类中所有 private 成员在派生类中不能使用。

2) protected继承方式

基类中的所有 public 成员在派生类中为 protected 属性;

基类中的所有 protected 成员在派生类中为 protected 属性;

基类中的所有 private 成员在派生类中不能使用。

3) private继承方式

基类中的所有 public 成员在派生类中均为 private 属性;

基类中的所有 protected 成员在派生类中均为 private 属性;

基类中的所有 private 成员在派生类中不能使用。

通过上面的分析可以发现:

1) 基类成员在派生类中的访问权限不得高于继承方式中指定的权限。

2) 不管继承方式如何,基类中的 private 成员在派生类中始终不能使用(不能在派生类的成员函数中访问或调用)。

3) 如果希望基类的成员能够被派生类继承并且毫无障碍地使用,那么这些成员只能声明为 public 或 protected;只有那些不希望在派生类中使用的成员才声明为 private。

4) 如果希望基类的成员既不向外暴露(不能通过对象访问),还能在派生类中使用,那么只能声明为 protected。

注意,我们这里说的是基类的 private 成员不能在派生类中使用,并没有说基类的 private 成员不能被继承。实际上,基类的 private 成员是能够被继承的,并且(成员变量)会占用派生类对象的内存,它只是在派生类中不可见,导致无法使用罢了。private 成员的这种特性,能够很好的对派生类隐藏基类的实现,以体现面向对象的封装性。



继承中的构造和析构

1、类型兼容性原则

类型兼容规则是指在需要基类对象的任何地方,都可以使用公有派生类(public继承的类)的对象来替代。通过公有继承,派生类得到了基类中除构造函数、析构函数之外的所有成员。这样,公有派生类实际就具备了基类的所有功能,凡是基类能解决的问题,公有派生类都可以解决。类型兼容规则中所指的替代包括以下情况:

子类对象可以当作父类对象使用

子类对象可以直接赋值给父类对象

子类对象可以直接初始化父类对象

父类指针可以直接指向子类对象

父类引用可以直接引用子类对象

在替代之后,派生类对象就可以作为基类的对象使用,但是只能使用从基类继承的成员。

类型兼容规则是多态性的重要基础之一。

2、继承中的构造析构调用原则

*子类对象在创建时会首先调用父类的构造函数

*父类构造函数执行结束后,执行子类的构造函数

*当父类的构造函数有参数时,需要在子类的初始化列表中显示调用

*析构函数调用的先后顺序与构造函数相反

在子类对象构造时,需要调用父类构造函数对其继承得来的成员进行初始化

在子类对象析构时,需要调用父类析构函数对其继承得来的成员进行清理

3、继承中的同名成员变量处理方法

当子类成员变量与父类成员变量同名时:

*子类依然从父类继承同名成员

*在子类中通过作用域分辨符::进行同名成员区分(在派生类中使用基类的同名成员,显式地使用类名限定符)

*同名成员存储在内存中的不同位置

1)重载:必须在同一个类中进行

子类无法重载父类的函数,父类同名函数将被名称覆盖

重载是在编译期间根据参数类型和个数决定函数调用

2)重定义:必须发生于父类与子类之间

父类与子类中的函数必须有完全相同的原型(如果用virtual关键字修饰,那叫重写)

4、派生类中的static关键字

继承和static关键字在一起会产生什么现象哪?

理论知识

基类定义的静态成员,将被所有派生类共享

根据静态成员自身的访问特性和派生类的继承方式,在类层次体系中具有不同的访问性质 (遵守派生类的访问控制)

派生类中访问静态成员,用以下形式显式说明:

类名 :: 成员

或通过对象访问 对象名 . 成员

多继承

一个类有多个直接基类的继承关系称为多继承

多继承声明语法

class 派生类名 : 访问控制 基类名1 , 访问控制 基类名2 , … , 访问控制 基类名n

{

数据成员和成员函数声明

};

多继承的二义性:

如果一个派生类从多个基类派生,而这些基类又有一个共同的基类,则在对该基类中声明的名字进行访问时,可能产生二义性

虚继承:解决多继承带来的二义性的问题

如果在多条继承路径上有一个公共的基类,那么在继承路径的某处汇合点,这个公共基类就会在派生类的对象中产生多个基类子对象

要使这个公共基类在派生类中只产生一个子对象,必须对这个基类声明为虚继承,使这个基类成为虚基类。

虚继承声明使用关键字 virtual
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: