概念:继承机制是面向对象程序设计使代码可以复用的最重要的手段
格式
class 派生类:继承方式 基类
类成员/继承方式 | public继承 | protected继承 | private继承 |
基类public成员 | 派生类的public成员 | 派生类的protected成员 | 派生类的private成员 |
基类的private成员 | 在派生类中不可见 | 在派生类中不可见 | 在派生类中不可见 |
基类的protected成员 | 派生类中的protected成员 | 派生类中的protected成员 | 在派生类中不可见 |
key
- 基类private成员在派生类中无论以什么方法继承都是不可见的,不可见指的是基类的私有成员还是被继承到了派生类对象中,但是语法上限制派生类对象不管在类里面还是类外面都不能去访问它
- 保护成员限制符是因继承才出现的
- 缺省的class继承权限是私有的,缺省的struct继承权限是公有的
基类和派生类对象赋值转换
- 派生类对象可以赋值给基类的对象/基类的指针/基类的引用(切片)
- 基类的指针可以通过强制转换赋值给派生类的指针,但是必须是基类的指针是指向派生类对象时才是安全的。反之使用虽然可行,但会存在越界访问的问题。
继承中的作用域问题
- 子类和父类中有同名成员,子类成员将屏蔽父类对同名成员的直接访问,这种情况叫隐藏,也叫重定义。(在子类成员函数中,可以用 基类::基类成员 显示访问)
- 同名函数隐藏:通过派生类来调用同名成员时先调用派生类自己的
派生类的默认成员函数
- 派生类的构造函数必须调用基类的构造函数初始化基类那一部分成员。如果基类没有默认的构造函数,则必须在派生类构造函数的初始化列表阶段显示调用
- 派生类的拷贝构造函数必须调用基类的拷贝构造完成基类的拷贝初始化
- 派生类的operator=必须要调用基类的operator=完成基类的复制
- 派生类的析构函数会在被调用完成后自动调用基类的析构函数清理基类成员,因为这样才能保证派生类对象先清理派生类成员再清理基类成员的顺序
- 派生类对象初始化先调用基类构造再调用派生类构造
- 派生类对象析构先调用派生类析构在调用基类的析构
赋值兼容规则:public继承
- 基类如果没有显式定义构造函数,派生类根据情况决定定义还是不定义、
- 基类中存在构造函数并且该构造函数是缺省的构造函数,派生类视自己的情况确定是否显式定义构造函数
- 基类显式定义了自己的非缺省的构造函数,派生类必须提供显式的构造函数
- 如若基类未进行缺省的构造,那么派生类必须在初始化的位置显式初始化该类,否则必须提供基类成员的构造
调用派生类的构造函数
:调用基类的构造函数,完成基类成员的构造
,初始化派生类自己的成员
{
执行构造函数的函数体
}
同名隐藏:基类与派生类具有相同名称的成员
成员变量:和基类与派生类同名成员的类型是否相同无关
成员函数:和基类与派生类同名的成员函数原型是否相同无关
派生类对象调用同名的成员,优先调用自己的同名成员
以上是C++继承中新学习到的知识,接下来结合之前的知识我们探讨继承的属性
友元关系可以继承嘛?
基类友元不能访问子类私有和保护成员(C++primer)
但是实际上在VS环境下
- 一个友元类的派生类,可以通过其基类接口去访问设置其基类为友元类的类的私有成员,也就是说一个类的友元类的派生类,某种意义上还是其友元类
- 一个派生类的基类的友元类仍然是它的友元类
- 基类的友元函数仍然是派生类的友元函数
那静态成员可以继承嘛?
基类定义了static静态成员,则整个继承体系里面只有一个这样的成员。
无论派生出多少个子类,都只有一个static成员实例
如何设置无法继承的类
1)私有化构造
2)提供内存在堆/栈的“=”操作符重载