参考链接
- https://www.bilibili.com/video/BV1et411b73Z?p=127
继承
概念
继承是面向对象三大特性之一。有些类与类直接存在特殊的关系,定义这些类时,下级别的成员除了拥有上一级的共性,还有自己的特性。这时就可以考虑利用继承的技术,减少重复代码
基本语法
class 子类:继承方式 父类
例如 class A:public B;
子类也称为派生类
父类也称为基类
继承方式
继承方式一共有三种:
- 公共继承
- 保护继承
- 私有继承
三种继承方式的区别如下图:
继承中的对象模型
- 父类中所有非静态成员属性都会被子类继承下去
- 父类中私有成员属性是被编译器给隐藏了,因此访问不到,但是确实被继承下去了
利用开发人员命令提示工具查看对象模型
- 挑战文件路径。cd 具体路径下
- 查看命名
- cl /d1 reportSingleClassLayout类名 文件名
继承中构造和析构顺序
-
子类继承父类后,当创建子类对象,也会调用父类的构造函数
-
先构造父类,再构造子类。析构的顺序和构造相反
继承同名成员处理方式
- 访问子类同名成员,直接访问即可
- 访问父类同名成员,需要加作用域
- 如果子类中出现和父类同名的成员函数,子类的同名成员会隐藏掉父类中所有同名成员函数。如果想访问到父类中被隐藏的同名成员函数,需要加作用域
同名成员变量
例如:
void test()
{
Son s;
cout << "Son 下m_A = " << s.m_A << endl;
//如果通过子类对象,访问到父类中同名成员,需要加作用域
cout << "Base 下m_A = " << s.Base::m_A << endl;
}
同名成员函数
void test()
{
Son s;
s.func(); //直接调用,调用的是子类中的同名成员
s.Base::func();
}
继承同名静态成员处理方式
静态成员和非静态成员出现同名,处理方式一致,只不过有两种访问方式(通过对象和通过类名):
- 访问子类同名成员,直接访问即可
- 访问父类同名成员,需要加作用域
- 子类出现和父类同名的静态成员函数,也会隐藏父类中所有同名成员函数。如果想访问父类中被隐藏的同名成员,需要加作用域
同名静态成员属性
void test()
{
//1. 通过对象访问
cout << "通过对象访问:" << endl;
Son s;
cout << "Son 下m_A = " << s.m_A << endl;
cout << "Base 下m_A = " << s.Base::m_A << endl;
//2. 通过类名访问
cout << "通过类名访问:" << endl;
cout << "Son 下m_A = " << Son::m_A << endl;
//第一个::代表通过类名方式访问,第二个::代表访问父类作用域下
cout << "Base 下m_A = " << Son::Base::m_A << endl;
}
同名静态成员函数
void test()
{
//1. 通过对象访问
cout << "通过对象访问" << endl;
Son s;
s.func();
s.Base::func();
//2. 通过类名访问
cout << "通过类名访问" << endl;
Son::func();
Son::Base::func();
}
多继承语法
C++允许一个类继承多个类
语法
class 子类:继承方式 父类1, 继承方式 父类2...
注意事项
-
多继承可能会引发父类中有同名成员出现,需要加作用域区分
-
C++实际开发中不建议用多继承
菱形继承
概念
- 两个派生类继承同一个基类
- 又有某个类同时继承这两个派生类
注意事项
- 当菱形继承,两个父类拥有相同数据,需要加以作用域区分
- 当这份数据只有一份就可以,菱形继承导致数据有两份,资源浪费。需要利用虚继承,解决菱形继承问题。
虚继承
继承之前,加上关键字virtual变为虚继承,父类称为虚基类。