- 多级派生的访问属性
我们前面所介绍类的继承都是只有一级派生的,那我们要是有派生的派生的情况又要如何判断所继承过来的属性呢,其实也非常非常简单,我们先来看一段代码:
A是B的直接基类,是C的间接基类。
那么我们先看B类继承过来的属性是什么,B继承A过来使用的是共有继承,所以所有属性不变都以A原来的属性继承过来,所以B中就有了共有成员(i,void f2( )),保护成员(void f1( ),void f3( )),私有成员(m)《这里就要问了,为什么没有私有成员k呢,因为基类的私有成员在派生类中不能直接访问因此属于不可见的,但是也是继承过来了》
那么C继承B是通过保护类型进行继承,再回顾一遍继承权限大小<private>protected>public>,所以原来在B中的共有成员,在C中将会变成保护类型,所以C中的类型是public(void f4( )),protected(I,void f2( ),void f1( ),void f3( )),私有成员有private(n).
因此我们可以总结出多级派生时的访问属性,我们依旧可以通过一级一级的看,和一级的时候的访问没有什么区别,大大小小也就是数量和类型改变时的注意罢了。
- 派生类的构造函数
因为我们派生类会将基类的成员继承过来,那么在派生类的构造函数中我们又要怎么做才能对其初始化呢。先来看一段代码:
看下来有什么感想呢?
从代码22行可以看到在派生类继承下来后的构造函数的形参列表里是派生类和基类所能继承过来的数据成员的总数据成员(倘若在基类是私有成员就没法对其直接赋值),后面就是:并且声明基类的类名及其它的数据成员,在函数体中则是派生类自己派生的成员进行赋值操作。
派生类构造函数一般形式为:
派生类构造函数函数名(总参数表):基类构造函数名(参数表)
当然,我们也可以用初始化表进行初始化:代码如下:
- 有子对象的派生类的构造函数
一、什么是子对象
当一个类的成员是某一个对象的类时,该对象就是子对象,驻留在另一个对象中的对象,在一个类的定义中,声明另一个类的对象用来作为成员变量。
二、子对象的作用是什么
减少代码重用
当一个类中出现了另一个类的对象成员时,该类的构造函数就要包含子对象的初始化(成员初始化列表放在构造函数的右边),并用冒号进行分隔。成员初始化列表是由一个或多个选项组成的,多各选项之间用逗号分隔
举一个代码例子:
运行结果:
因此对象的初始化是在建立派生类是通过调用派生类构造函数来实现的。
派生类构造函数有一下三个部分需要填写:
(1).对基类数据成员初始化;
(2).对子对象数据成员初始化;
(3).对派生类数据成员进行初始化
所以总结下来,派生类构造函数的一般形式为:
派生类构造函数名(总参数表):基类构造函数名(参数表),子对象名(参数表)
{派生类中新增数据成员初始化语句}
执行派生类构造函数的顺序是:
(1).调用基类构造函数函数,对基类数据成员初始化;
(2).调用子对象构造函数,对子对象数据成员初始化;
(3).再执行派生类构造函数本身,对派生类数据成员初始化;
(4).析构函数则相反;
- 多层派生时的构造函数
代码举例:
运行结果:
由此可以看出,我们在多层派生的时候的构造函数是只写出上一层类(也就是直接基类)的构造函数就行。
基类的构造函数首部:
Student(int n,string nam)
派生类Student1的构造函数首部:
Student1(int n, string nam, int a):Student(n,nam)
派生类Student的构造函数首部:
Student2(int n,string nam,int a,int s):Student1(n,nam,a)
就是只写出直接基类的构造函数就对了。
派生类构造函数的特殊形式:
(1).当不需要对派生类新增的成员进行任何初始操作时,派生类构造函数的函数体可以为空,即构造函数是空函数。
(2).如果在基类中没有定义构造函数,或定义了没有参数的构造函数,那么,在定义派生类构造函数时可以不写基类的构造函数。
- 派生类的构造函数
其实并没有什么特殊的地方,在派生类中可以更具需要定义自己的析构函数,用来对派生类中所增加的成员进行清理工作,基类的清理工作仍然由基类的析构函数负责。
析构函数的调用顺序和调用构造函数的顺序相反。
- 基类与派生类的转换
(1).只有共有派生类才是基类真正的子类型,它完整地继承了基类的功能。
基类与派生类的转换具体表现在以下几种方面:
(1).派生类对象可以向基类对象赋值:
可以用子类(即公用派生类)对象对其基类对象赋值。在赋值时舍弃派生类自己的成员,也就是“大材小用”。就是使用派生类对基类赋值的时候,会舍弃掉原来派生类自己派生的数据成员。只能用子类对象对其基类对象赋值,而不能用基类对象对子类对象赋值。
(2).派生类对象可以替代基类对象向基类对象的引用进行赋值或初始化。如:
(3).如果函数的参数是基类对象或基类对象的引用,相应的实参可以用子类对象。
(4).派生类对象的地址可以赋给指向基类对象的指针变量,也就是说,指向基类对象的指针变量也可以指向派生类对象。(也就是用指向基类的指针,再指向派生类,但是拥有的成员也依旧还是基类的数据成员)