C++:12.继承与派生

为了支持代码的复用,继承与派生在C++中就显得十分重要。


继承与派生:

当定义一个新的类 B 时,如果发现类 B 拥有某个已写好的类 A 的全部特点,此外还有类 A 没有的特点,那么就不必从头重写类 B,而是可以把类 A 作为一个“基类”(也称“父类”),把类 B 写为基类 A 的一个“派生类”(也称“子类”)。这样,就可以说从类 A “派生”出了类 B,也可以说类 B “继承”了类 A。

基类的所有成员都自动称为派生类的成员。派生类可以在其基础上添加和修改

举个栗子:学生类作为基类,成员函数中打印函数可以打印姓名、性别。本科生类作为派生类,成员函数中要多打印一个专业。那么可以在本科生类中写一个与学生类中打印函数同名的函数,先调用学生类中的打印函数,在单独打印专业这一信息。通过派生类对象访问同名成员,除非特别指明,否则访问的就是派生类的成员,这种情况叫“覆盖”,即派生类的成员覆盖基类的同名成员。

派生类对象占用的存储空间大小  =  基类对象占用存储空间大小  +  派生类对象自身成员变量占用存储空间大小。

类与类之间的关系有两种:组合和继承。组合指的是A是B的一部分。继承指的是A是B的一种。


protected:

之前一直使用的是public与private。protected修饰的是保护成员,它的可访问范围介于public与private之间。

设置protected的目的:无论派生类是用何种方式继承的基类,基类中的私有成员在派生类中都是无法访问的。但是派生类的成员函数又确实需要经常访问基类成员。所以我们将它设置为保护成员,既可以起到隐藏的目的,又可是让派生类访问它。(保护成员可以在派生类访问,但不能在其他地方访问。)

如果不写继承方式:最好还是写上!

派生类用struct定义,默认继承方式就是public。派生类用class定义,默认继承方式就是private。


派生类的构造函数和析构函数:

由于派生类中包含基类成员,所以在执行派生类构造函数的时候,都会先执行基类的构造函数(在构造函数的参数列表中,如果不在初始化列表中,写在内部,它的意思就先构造派生类了,肯定是错的)。如果对此不做说明,编译器会调用基类的无参构造函数,如果没有无参构造函数,就会报错。

析构函数的调用依旧满足:先构造的后析构,后构造的先析构的特点。

多层次的派生:

A类 派生 B类,B类 派生 C类。

则 A类 是 B类 的直接基类,B类 是 C类 的直接基类,A类 是 C类 的间接基类。

在 C类 写派生关系的时候,只写直接基类 B类,不写间接基类 A类。

调用构造函数的时候会先构造最上面的基类,之后依次往下。

当组合与派生同时使用:

先调用基类的构造函数,再按照成员对象的定义顺序执行各自的构造函数。


基类与派生类赋值(初始化)规则:

  • 派生类对象可以赋值给基类对象。
  • 派生类对象可以用来初始化基类引用。
  • 派生类的指针可以赋值给基类的指针。

结论:继承结构中,默认支持从下到上的转换,反过来不行的。

理解一下:派生类包含基类,派生类是个大圈里面有个小圈是基类。大的(派生类)给小的(基类)赋值可以,你小的(基类)给大的(派生类)只能赋一部分,剩下的就浪费了所以不合适。      虽然说大的(派生类指针)可以给小的(基类指针)赋值,但不属于小的(基类指针)那一部分,小的(基类指针)也是无法访问的。(也就是说不能通过基类指针访问基类没有而派生类中有的成员。

还有一点:虽然小的(基类指针)不能赋值给大的(派生类指针),但你要强制类型转换,编译器当然也会认可。但这种情况下需要保证那个基类指针本身就指向一个派生类对象。不然会出错。慎用!!!!


基类与派生类同名成员的访问:

同名成员方法的关系:重载、隐藏、覆盖

重载

在基类或者派生类同一个类作用域当中的,函数名相同,参数列表不同。

隐藏

方法分布在基类和派生类中

只要方法名字相同(无论参数个数或参数类型是否相同),就说派生类的同名方法把基类的同名方法给隐藏了。

覆盖

方法分布在基类和派生类中

基类的方法是虚函数,派生类的方法和基类的虚函数,返回值相同,函数名相同,参数列表也相同。那么就会用派生类的函数覆盖掉基类的虚函数。在虚函数表中进行覆盖!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章