继承

作者: 我非神灵 | 来源:发表于2023-08-23 14:57 被阅读0次

继承的好处:

1、可以做代码的复用

2、在基类中给所有派生类提供统一的虚函数接口,让派生类进行重写,然后就可以使用多态了

一:继承的本质和原理

继承的本质:a.代码的复用

b.类和类直接的关系:

组合:a part of ~ ~的一部分

继承:a kind of ~ ~的一种

继承方式 基类的访问限定 派生类的访问限定 外部访问
public public public Y
protected protected N
private 被继承但不可见 N
protected public protected N
protected protected N
private 被继承但不可见 N
private public private N
protected private N
private 被继承但不可见 N

总结:

  • 外部只能访问对象public的成员,protected和private的成员无法直接访问
  • 再继承结构中,派生类从基类可以继承private的成员,但派生类无法直接访问
  • protected和private的区别?在基类中定义的成员,想被派生类访问,但不想被外部访问,那么在基类中把相关成员定义成protected;如果派生类和外部都不打算访问,那么在基类中,就把相关成员定义成private的

默认的继承方式

class定义派生类,默认继承方式是private

struct定义派生类,默认继承方式是public

二:派生类的构造过程

派生类对象构造和析构的过程是:

1.派生类调用基类的构造函数,初始化从基类继承来的成员

2.调用派生类自己的构造函数,初始化派生类自己特有的成员

....派生类对象的作用域到期→

3.调用派生类的析构函数,释放派生类成员可能占用的外部资源(堆内存,文件)

4.调用基类的析构函数,释放派生类内存中,于从基类继承来的成员可能占用的外部资源(堆内存,文件)

派生类怎么初始化从基类的成员变量?

1 派生类从继承可以继承来所有的成员变量(变量和方法),除了构造函数和析构函数

ans:通过调用相应的构造函数

派生类的构造函数和析构函数,复杂初始化和清理派生类部分

派生类从基类继承来的成员的初始化和清理由基类的构造函数和析构函数来负责

三:重载、隐藏、覆盖

1.重载关系

一组函数要重载,必须处在同一个作用域当中;而且函数名字相同,参数列表不同(本质是根据参数来决定调用哪个函数)

2.隐藏(作用域的隐藏)的关系

在继承结构当中,派生类的同名成员,把基类的同名成员给隐藏调用了(即对函数选择的优先级)

3.覆盖:

基类和派生类的方法,返回值、函数名以及参数列表都相同,而且基类的方法是虚函数,那么派生类的方法就自动处理成虚函数,它们之间成为覆盖关系(本质是根据发起调用的对象来决定调用哪个函数)

基类对象(上)→派生类对象(下)

派生类对象→基类对象

基类指针(引用)→派生类对象

派生类指针(引用)→基类对象

虚函数,静态绑定和动态绑定

类添加了虚函数,对这个类有什么影响?

总结一:

一个类里面定义了虚函数,那么编译阶段,编译器给这个类类型产生一个唯一的vftable虚函数表,虚函数表中主要存储的内容就是RTTI指针和虚函数的地址。当程序运行时,每一张虚函数表都会加载到内存的.rodata区。

总结二:

一个类里面定义了虚函数,那么这个类定义的对象,其运行时,内存中开始部分,多存储一个vfptr虚函数指针,指向相应类型的虚函数表vftable。一个类型定义的n个对象,它们的额vfpt指向的都是同一张虚函数表

总结三:

一个类里面虚函数的个数,不影响对象内存大小(vfptr),影响的是虚函数表的大小

总结四:

如果派生类中的方法,和基类继承来的某个方法,返回值、函数名、参数列表都相同而且基类的方法是virtual/虚函数,那么派生类的这个方法,自动处理成虚函数重写↔覆盖

/*
pb->BaseBase:show //如果发现show是普通函数,就进行静态绑定call Base:show
pb->Base Base:show //如果发现show是虚函数,就进行动态绑定了
mov eax,dword ptr[pb]
movecx,dword ptr[eax]
call ecx    // (虚函数的地址)动态(运行时期)的绑定(函数的调用)
*/
pb->show(); //静态绑定调用 call base::show

哪些函数不能实现成虚函数

虚函数依赖:

1.虚函数能产生地址,存储在vftable中

2.对象必须存在 虚函数表指针在对象内存中

构造函数调用时对象还未存在,故其无法成为虚函数

构造函数中调用虚函数,也不会发生动态绑定

派生类构造过程:先调用基类的构造函数→调用派生类的构造函数

是不是虚函数的调用一定就是动态绑定?

在类的构造函数中,调用虚函数,也是静态绑定(构造函数中调用其他函数(虚),不会发生动态绑定)

必须由指针(或者引用)调用虚函数才会发生动态绑定

相关文章

  • 继承 继承

    属性拷贝 继承不单单能通过原型链实现,也能通过其他方式实现,属性拷贝就是其中一种方法。 通过属性拷贝也能实现继承子...

  • 继承(单继承,多继承)

    将共性的内容放在父类中,子类只需要关注自己特有的内容 python中所有的内容都是对象,所有的对象都直接或间接继承...

  • js继承方式

    类式继承 构造函数继承 组合继承 类式继承 + 构造函数继承 原型式继承 寄生式继承 寄生组合式继承 寄生式继承 ...

  • Python-学习之路-08 OOP -02

    单继承和多继承 单继承:每个类只能继承一个类 多继承:每个类可以继承多个类 单继承的多继承的优缺点 菱形继承/钻石...

  • 原型相关(二)

    1.继承 继承方式:接口继承(只继承方法签名)实现继承(继承实际的方法)ECMAScript只支持实现继承,并且主...

  • 继承

    继承的引入和概述 继承案例和继承的好处 继承的弊端 Java中继承的特点 继承的注意实现和什么时候使用继承 继承中...

  • Java面向对象三大特性之继承

    继承 一、继承的特点 Java只支持单继承单继承 多继承 单继承、多继承优缺点①单继承优点:提高了代码的复用性,让...

  • 7、面向对象的程序设计3(《JS高级》笔记)

    三、继承 许多OO语言都支持两种继承方式:接口继承和实现继承。接口继承只继承方法签名,而实现继承则继承实际方法。由...

  • 【重学前端】JavaScript中的继承

    JavaScript中继承主要分为六种:类式继承(原型链继承)、构造函数继承、组合继承、原型式继承、寄生式继承、寄...

  • js之继承

    文章主讲 JS 继承,包括原型链继承、构造函数继承、组合继承、寄生组合继承、原型式继承、 ES6 继承,以及 多继...

网友评论

      本文标题:继承

      本文链接:https://www.haomeiwen.com/subject/ldmpmdtx.html