每日一面——虚函数、动态绑定、静态绑定

本文详细解释了C++中虚函数的实现原理,包括虚函数表和虚函数指针的作用;探讨了构造函数和析构函数不能声明为虚函数的原因;区分了动态绑定和静态绑定的概念,并说明了static函数和内联函数不能作为虚函数的原因。
摘要由CSDN通过智能技术生成

写前声明:参考链接 C++面经面试宝典

✊✊✊每日一面——虚函数、动态绑定、静态绑定

    • 一、虚函数是怎么实现的?它存放在哪个内存的哪个区?什么时候生成
    • 二、构造函数和析构函数为什么不可以声明为虚函数?
    • 三、动态绑定和静态绑定是怎么实现的?
    • 四、类中static函数和内联函数能否声明为虚函数?

一、虚函数是怎么实现的?它存放在哪个内存的哪个区?什么时候生成

在C++中,虚函数的实现原理基于两个关键概念:虚函数表和虚函数指针

  • 虚函数表:每个包含虚函数的类都会生成一个虚函数表,其中存储着该类中所有的虚函数地址,虚函数表是一个由指针构成的数组,每个指针指向一个虚函数的实现代码
  • 虚函数指针:在对象的内存布局中,编译器会添加一个额外的指针,称为虚函数指针或虚表指针,这个指针指向该对象对应的虚函数表,从而让程序能够动态的调用虚函数

当一个基类指针或引用调用虚函数时,编译器会使用虚表指针来查找该对象对应的虚函数表,并根据函数在虚函数表中的位置来调用正确的虚函数

在编译阶段生成,虚函数和普通函数一样存放在代码段,只是它的指针又存放在了虚表之中

二、构造函数和析构函数为什么不可以声明为虚函数?

1)在C++中,虚函数的调用是通过虚函数表来实现的。但是在对象创建的过程中,由于对象还没有完全构造成功,因此在构造函数和析构函数中不能使用虚函数,这是因为在对象构造期间,虚函数表尚未构建,而且对象还没有完成其完整的初始化。此外,构造函数的调用顺序是从基类到派生类,因为基类部分先于派生类部分构建,如果基类构造函数是虚函数,那么它将无法正常地被调用,因为调用虚函数之前必须先构造对象。同样,派生类构造函数也不能是虚函数,因为派生类的构造函数必须调用其基类的构造函数,如果基类的构造函数是虚函数,将无法保证正常的顺序。因此,类的构造函数不能是虚构函数。如果需要在对象的生命周期内支持多态性,可以使用虚析构函数来实现

2)析构函数可以被声明为虚函数,因为当基类指针指向派生类对象的时候,发生多态,如果不将基类的析构函数定义为虚函数的话,那么派生类的析构函数就无法执行,造成内存泄露

补充:

  • 虚函数通过使用 virtual 关键字来声明,如果一个函数被声明为虚函数,那么当通过指向对象的指针或者引用调用该函数时,程序将会根据对象的实际类型来调用相应的函数,而不是根据这种指针或者引用的类型来调用函数
  • 为了实现这一机制,C++编译器会在对象的内存布局中添加一个虚函数表(virtual table,也称 vftable)。虚函数表是一个指向虚函数的指针数组,每个虚函数在数组中对应一个条目。当调用虚函数时,程序会通过对象的虚函数表找到对应的虚函数并调用它
  • 值得注意的是:只有通过使用基类对象的指针或引用调用虚函数才会触发动态绑定机制,即根据对象的实际类型来调用函数,如果直接使用普通基类对象,则会按照静态绑定的方式调用虚函数

三、动态绑定和静态绑定是怎么实现的?

  • 静态绑定:变量在声明时的类型,是在编译阶段确定的,静态类型不能更改
  • 动态绑定:模板所指对象的类型,是在运行阶段确定的,动态类型可以更改

四、类中static函数和内联函数能否声明为虚函数?

  • 不能,因为类中的static函数是所有类实例化对象所共有的,没有 this 指针,而虚函数依靠 vfptr 和 vftable 来处理,vfptr 是一个指针,在类中的构造函数中生成,并且只能通过 this 指针访问,对于静态成员函数而言,由于其没有 this 指针,无法访问 vfptr,因此也无法被声明为虚函数
  • 不能,inline内联函数在编译时会直接将函数题嵌入到函数的调用点,没有函数调用的开销,而虚函数是通过虚函数表来确定,无法进行内联
  • 16
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

leisure-pp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值