C++虚函数

本文深入探讨了C++中的虚函数机制,包括派生类如何处理未覆盖的虚函数、虚函数表的工作原理、纯虚函数的作用以及虚析构函数的重要性等。还介绍了在构造函数和析构函数中调用虚函数的行为。
  1. 派生类如果没有覆盖虚函数则会自动使用之前的定义。
  2. 一个类如果没有数据成员,C++编译器会自动插入一个char类型。这样保证了每个对象都有不同的地址。
  3. 基类和派生类会在同一个地方有VPTR(经常是对象开始的位置)。
  4. 虚函数调用需要两步复杂的汇编指令,而普通函数需要一步指令
  5. 如果想通过指针或引用调用虚函数,那么虚函数不能是内联函数。因为内联函数没有地址,而虚函数通过虚表中的函数地址调用。
  6. 抽象基类不能实例化,只是一个接口。
  7. 通过定义纯虚函数,我们告诉编译器在虚表中保留一个槽的位置,但不放入任何函数的地址。
  8. 纯虚函数显示声明了一个类的抽象性。
  9. 纯虚函数避免了值传递的函数调用(本意是想通过引用或者指针触发多态)。也避免了向上转型中值传递造成的裁剪。
  10. 纯虚函数可以有定义。这样的话,虚表中的槽仍然是空的,但是派生类中可以调用那个函数。(也就是在派生类中对应的那个槽填入了函数地址)
  11. 编译器为你创建的新类型创建一个虚表,在虚表中插入新的函数地址,如果你没有覆盖原来的函数,则函数地址是基类的函数地址。
  12. 因为编译器产生的代码使用数值偏移在虚表中选择虚函数,所以同名函数所在槽的位置在基类和派生类中是相同的。
  13. 编译器使用指向基类的指针时,只能调用基类的函数。(如果没有向下转型)
  14. 值传递时,编译器为基类使用拷贝构造函数,并初始化虚表指针指向基类的虚表。
  15. 对于14,你可以通过在基类中设置一个纯虚函数来避免裁剪。
  16. 对于构造函数,编译器会偷偷在其中插入代码来做以下几件事情 A)初始化虚表指针; B)检查this的值,因为operator new可能返回空指针; C) 调用基类构造函数; 构造函数的大小带来的损失可能会大于你节省的函数调用的开销,如果你调用了很多次内联构造函数,那么你的代码量可能会暴增哦。
  17. 你应该尽可能在初始化列表中初始化所有成员对象。
  18. 虚函数的机制在构造函数中不生效。(如果生效,那么你可能在调用一个使用派生类数据的虚函数,而那个数据还没有初始化。)
  19. 每个构造函数都会初始化虚表指针,所以虚表指针由最后的派生类决定。
  20. 在构造函数中调用虚函数会调用那个类的版本的虚函数。(前期绑定)
  21. 虚函数可以并且经常是虚函数。
  22. 你应该记住构造函数和虚函数是唯二的两个地方,我们调用一个函数,会引起整个系列函数的调用。
  23. 如果你创建一个纯虚的析构函数,你必须提供函数体,因为一个类层次中,所有的析构函数总会被调用。
  24. 基类的纯虚析构函数会强迫派生类覆盖析构函数,但基类的函数提仍然是析构的一部分。
  25. 一旦你在类中有了一个虚函数,你应该立马加上一个虚析构函数。
  26. 析构函数中调用虚函数也是调用那个类的版本的虚函数。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值