C++学习笔记10

多态

含义

多态是面向对象程序设计语言中数据抽象和继承之外的第三个基本特征,是指对于同一个消息或同一种调用,在不同的场合或不同的情况下,会执行不同的行为。在子类函数前加上virtual关键字,并在父类上声明虚函数,就会发生多态。多态的实质就是父类的引用或指针绑定或指向子类对象。

分类
  1. 静态多态(函数重载)
  2. 动态多态(虚函数,继承关系)
    二者区别
    静态联编:地址早绑定,在编译阶段绑定好地址;函数重载,运算符重载
    动态联编:地址晚绑定;继承+虚函数
注意
  • 在函数声明前加上virtual称为虚函数
  • 构造函数不能设为虚函数
  • static成员函不能设为虚函数,因为static成员函数无this指针,而虚函数需要this加以调用
  • 当基类定义了虚函数时,若派生类重定义虚函数(即使不加virtual关键字),也是虚函数
  • 如果派生类要覆盖基类的虚函数,必须要与基类的虚函数形式一致
  • 当基类定义了虚函数之后,在其存储布局的开始位置会多一个虚函数指针,该指针指向一张虚函数表,虚函数表中存储的是虚函数的入口地址
多态的原理

当父类中有了虚函数后,内部结构就发生了改变,内部会多一个vfptr即虚函数指针,指向vftable(虚函数表),子类会继承vfptr,vftable,子类的构造函数会将vfptr指向自己的vftable,如果发生了重写,会替换虚函数表中原有的函数。

虚函数(动态多态)机制被激活的条件
  • 基类有定义虚函数,派生类覆盖基类虚函数
  • 创建派生类对象
  • 用基类的指针或引用指向派生类对象
  • 用基类指针或引用调用虚函数
纯虚函数

简言之:其作用就是提供统一的接口
定义了纯虚函数的类称为抽象类,无法实例化对象
特点:①没有实现 ②作为接口存在
派生类继承基类之后,如果基类中存在多个纯虚函数,则派生类必须实现全部的纯虚函数,否则无法实例化对象。
开闭原则:对扩展开放,对修改关闭。在开发过程中,最好遵循此原则,能在最大程度上保证系统的平滑升级。

虚继承
实现

1.存在即表示继承体系和虚基类确定存在
2.间接性表现在当访问虚基类的成员时同样也必须通过某种间接机制(vftable)完成
3.共享性表现在虚基类会在虚继承体系中被共享,而不会出现多份拷贝
如果派生类拥有自己的虚函数,此时派生类对象就会产生自己本身的虚函数指针,并且该虚函数指针位于派生类对象存储空间的开始位置

虚析构和纯虚析构

普通析构不会调用子类的虚构函数,需要在虚构函数之前加上virtual关键字,可以解决由父类指针指向子类释放时不彻底的问题
在虚析构函数声明之后加上 “= 0”即成为纯虚析构函数,纯虚析构函数需要在类内声明,类外实现。如果出现纯虚析构函数,这个类也算是抽象类,即无法实例化对象

虚拟继承的内存布局规则

单个类,不带虚函数
  虚继承与继承的区别:①多了一个虚基指针 ②虚基类位于派生类存储空间的末尾
单个类,带虚函数
  ①如果派生类没有自己的虚函数,此时派生类对象不会产生虚函数指针
  ②如果派生类拥有自己的虚函数,此时派生类对象会产生自身的虚函数指针,并且该虚函数指针位于派生类对象存储的开始位置
多重继承,带虚函数
  ①每个基类都有自己的基函数表
  ②如果派生类有自己的虚函数,会被加入到第一个虚函数表中
  ③派生类的内存布局中,其基类布局按照基类被声明的顺序进行排列
  ④派生类会覆盖基类的虚函数,第一个虚函数表中存放的并不是真实的虚函数的地址,而只是一条跳转指令
钻石型虚继承
  ①虚基指针的第一条内容表示的是该虚基指针距离所在子对象首地址的偏移
  ②虚基指针的第二条内容表示的是该虚基指针距离虚基类子对象的首地址的偏移

字节对齐
#pragma pack(push)
#pragma pack(4)//以4字节对齐
#pragma pack(pop)//恢复原始对齐方式
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值