便于管理系统中的对象
系统扩充比较容易- 利用程序代码的再用性
加快程序发展的速度
减少程序的错误
3、继承例子:家具和柜子 建筑和房子 动物和猫
:class 派生类名:继承方式 基类名{派生类新增成员与方法的声明}
:类的三种访问权限—public protecd private
继承的时候没有写继承方式,默认私有继承。
在类中,我们是设计师,public, private, protected三种成员可以访问
在对象中,我们是使用者,只有规定的接口public才可以访问;protected, private不能访问
① 公有成员(public):可以被任何普通函数和任何类的成员函数访问(类和类外都可以访问)
② 私有成员(private):可以被类自身的成员和友元访问,但不能被包括派生类在内的其他任何类和任何普通函数访问。(只能自己类内)
③ 保护成员(protected):可以被类自身的成员和友元访问外,还可以被派生类的成员函数访问,但不能被任何非友元的普通函数访问。(无继承关系,和private一样;有继承关系,派生类可访问基类protected)
Ps:都可以在类内访问,只有public可以在类外访问。
存在继承情况时:
派生类可以直接访问父类的public、protected修饰的成员。
成员变量一般使用私有访问控制。
成员方法如果想要让子类访问,但是不想让外界访问,可以使用受保护的访问控制。
(1)提高代码的复用性
避免重复代码,减少代码的冗余。
(2)提高代码的维护性
只需要修改一次父类的一些方法,不用每个子类修改。便于扩充。
(3)类与类之间产生了关系,是多态的前提。
(1)类的耦合性增加了
开发原则:高内聚,低耦合
耦合:类与类的关系
内聚:自己完成一件事的能力
继承关系中的派生类创建对象:构造的执行顺序先走基类的构造,再走派生类的构造,
继承关系中的派生类释放对象:先走派生类的析构,再走基类的析构


子类和父类出现同名非静态成员或函数,那么通过子类对象去访问该成员,访问的是子类中的成员。若子类没有父类中的成员,子类访问是父类的。
如果存在同名成员,但子类想访问父类该成员,需要加上作用域。(Son.base::m_A)
如果子类存在和父类同名的成员函数,子类会所有和父类同名的成员函数。(子类重定义父类的成员函数)
如果想要调用父类中同名的成员函数,必须加上作用域。(son.Base::fun_c(10);)
(1)通过对象访问
静态成员:static修饰,编译的时候就分配好了内存,类的所有对象都共享,类内(.h)声明,类外(.cpp)初始化。初始化格式:数据类型 类名::成员变量名=初始值;
子类和父类出现同名静态成员,那么通过子类对象去访问该成员,访问的是子类中的成员。
静态函数:子类和父类出现同名静态函数,那么通过子类对象去访问该函数,访问的是子类中的函数。要想访问父类同名函数,需使用域运算符。
(2)通过类名访问
类名::成员名或者函数名
Son::m_A; Base::m_A; Son::Base::m_A;
含义:一个类继承多个类
语法格式:class 子类名 :继承方式 父类1,继承方式 父类2…(继承方式最好不要省略,默认为私有继承)
特性
(1) 若两个父类含有同名成员,子类访问需要加上作用域。
定义:两个派生类(B、C)继承同一个基类(A),又有一个类(D)同时继承着两个派生类。
问题:
B、C同时继承A,当C访问A成员的时候,不知道访问的是B中的A还是C中的A,产生二义性。(解决:加作用域)
C继承A的数据有两份,浪费内存。
解决:使用虚继承,就不会产生二义性,C类可以直接访问赋值A成员。C.m_A=200;(若不是虚继承,这句就会报错,要加上B或C作用域)
语法格式:B、C类继承A类时 class B:virtual public A{} 加virtual,A被称为虚基类。
虚继承前,D类有两个A类的成员,分别通过B、C访问。
虚继承后,D类就只有一个A类的成员
Vbptr:虚基类指针
原理:只有一个唯一的成员,通过保存虚基类指针,这个指针指向的是一张表(虚基类表)
这个表中保存了当前获取到唯一的数据的偏移量。
虚表:
每一个类都有一个虚表,虚表里放的是虚函数的地址,基类被很多派生类继承,派生类也有虚表,派生类中如果没有重写虚函数,那么派生类中虚表中保存的函数的地址是基类的虚函数的地址;如果自己有重写过虚函数,虚表中存放的是派生类中虚函数的地址。