继承
基类,派生类,转化切片
继承允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。在派生类中,会额外新建成员变量 ,而不会新建成员函数,但对于静态成员来说,它并不会新建 —— 成员函数被保存到了公共代码区。
- 在派生类中,成员的访问方式取权限较小的那个,并且只允许向上转换——派生类赋值给父类 ,反之则不成立。
- 友元关系不能继承。
使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public,不过
最好显示的写出继承方式。
基类private成员在派生类中无论以什么方式继承都是不可见的。如果基类成员不想在类外直接被访问,但需要在派生类中能访问,就定义为protected。
赋值兼容转换(切片)
发生在派生类赋值给父类的时候,并不会发生类型转换中常现的临时变量,而是直接将派生类当作一种特殊的父类,找到父类需要的部分将其分割出去。
切片的别名,指针
其中 p_p1 是 s1 中父类那一部分的别名。
1 |
|
指针同理,如下图中:
ptrp指向s中父类的那一部分。
基类的指针可以通过强制类型转换赋值给派生类的指针
同样也是向上转换,基类变为派生类,但注意越界访问的问题。
作用域
域:是一种编译器在语法检查阶段的查找规则,查找默认具有就近原则。
默认是:局部域,函数域,当前类域
,父类域,全局域。
隐藏/重定义
子类和父类只要有同名成员,子类的成员就会隐藏父类的成员。如果想访问父类成员的话,需要在成员前指定父类域。
易出题,如找不到成员函数,可能会编译报错,并且,尽量不要在继承体系当中定义重名成员
初始化
在派生类中,不可以显示的在初始化列表中初始化基类成员。
规定:派生类若想要初始化父类的成员,默认情况下会调用父类的默认构造
在初始化列表中,对于内置类型不做处理,自定义类型调用他们的构造函数,而对于基类来说,则是将他们当作一个整体,直接去调用基类的默认构造
如果想要调用People(int id) ,那么就需要如下的方法:people(0)
派生类的拷贝构造
实验代码如下
1 |
|
核心:基类和派生类各干各的,如果想要在派生类中使用赋值拷贝,那么就在这个过程中使用基类的赋值拷贝。子不能用父,父不能用子
例如:
继承的析构函数
不需要显示调用。
由于多态的原因,所有析构函数的函数名都被处理为了destructor,所以在派生类调用基类的析构时,需要指定基类域——但实际上都使用自动调用,用于保证析构顺序——先完成子类析构,再调用父类析构,因为子类中可能使用父类的成员,而父类不会使用子类。
不同与构造函数中,由于父类的声明始终先于子类的成员,所以构造的顺序始终都是先父后子,并且也没有像析构那样自动调用。
如何避免继承
将不想被继承的类的构造(析构)函数私有化。并且为了防止无法创建该类的问题,还需要创建一个公有的静态成员函数,用于创建或者释放(static可以解决没有对象却可以调用成员函数的问题)**
final:基类加一个final。(C++11)