继承和派生
属于父子关系,站在儿子的角度是继承,站在父亲的角度是派生
-
为什么要引入继承和派生
解决软件重用性问题(C语言问题就是在一个项目中写好拿到另一个项目中不能用),实现了代码的重用性
-
怎么使用?
- 语法:class 派生类名:[继承方式] 基类名
{
派生类成员声明
};
子类继承父类会全盘接收,除了构造器和析构器,基类就可能会造成派生类的冗余,这是面对对象无法克服的,需要去设计一个好的基类
-
初始化
构造、析构、拷贝构造、赋值运算符重载以什么形式到子类中呢?
-
构造:类内的子对象要么显示的初始化(通过传参调用其构造函数),要么不显示初始化自动调用无参的构造器,如果既不显示也没有无参构造器的话会报错。进而推得:子类的初始化中不一定要调用父类的构造器,要么显示调用构造器传参,要么父类有无参构造器或是默认参数的函数可以包含(无参构造器)。
子类继承了父类的私有成员(可以通过sizeof查看类的大小),只是无法直接访问,所以需要通过父类的构造函数初始化,调用父类的接口函数使用
-
析构:析构顺序(子类->成员->基类)
-
拷贝构造:如果都是浅拷贝则不用重新写,如果是深拷贝需要在重新写,其中派生类中的默认拷贝构造器会调用父类中默认或者自实现的拷贝构造器,若派生类实现拷贝构造器,则必须显示的调用父类的拷贝构造器。
-
赋值运算符重载:派生类的默认赋值运算符重载函数,会调用父类的赋值运算符重载函数(默认或自实现),若派生类自实现赋值运算符重载函数,不在发生默认调用,需要手动显示调用(不调用也不报错,但是有问题的)
-
-
继承方式 (用public就完事了)
-
访问方式 public private protected ,在访问方式上protected同private
-
在public下,父类的public在子类可以访问,并且外面可以访问;父类的protected在子类可以访问,但外面不可访问,privated子类中不可访问,外面更不可访问
-
继承方式影响了基类中成员在子类中的访问方式 ,父类是有条件的继承给子类
-
pri的内容虽然不能继承,但可以通过函数在public中返回pri的内容,然后间接被继承
-
访问方式 \ 继承方式 public(99%) protected private public public protected private protected protected protected private private inaccess inaccess inaccess -
多级派生
public 传承接口 传承数据 public public public pub 接口 pub pub pub pro 接口/数据 pro pro pro pri 数据 protected 传承数据 protected protected protected pub 接口 pro pro pro pro 接口/数据 pro pro pro pri 数据 private 封杀了接口和数据 private private private pub 接口 pri pro 接口/数据 pri pri 数据
-
多级派生中:public兼容了数据的隐蔽性(外面无法访问)、接口传承、数据传递,protected只兼顾了数据的隐蔽性和数据传递,private只兼顾了数据的隐蔽性
- 既然都用public如此为什么还要用protected和private?防止基类公用接口的扩散,例如有一些类库公司不想让别人看到内部是怎么做的。
-
多继承
-
语法
-
多继承可以继承好几个爹,但也有问题:多个父类中有同名的成员,被继承到子类中会给访问带来不方便,浪费空间
c++提供虚基类和虚继承机制,实现在多继承中只保留一份共同成员,解决多继承当中同名成员被继承后引起的访问混乱
-
虚基类:提取公因式 M类,是设计和抽象的结果
-
虚继承 virtual:一种继承的扩展 解决了避免从多个父类中继承同名的成员
语法 class 派生类名:virtual 继承方式 基类名
-
-
多继承会造成三角问题,就存在不同父类重名问题,为了解决将三角问题变成钻石/四角问题,抽象出M类,形成了爷(基类)父(中间类)孙(派生类),但打破了隔辈不管的原则,在初始化中孙子开始管爷爷了,中间类不受virtual的影响,像普通类一样使用,virtual的发生阶段在生产孙子类的时候生效。
-