常用知识点

一、C++

1. 多态与虚函数

1.1 什么是多态?

同一函数名却有多种状态,即一个接口有多种不同行为。

1.2 如何实现?

  • 编译时多态
    静态联编,通过 重载模板 来实现。
    • 模板:在编译期间,编译器推断出模板参数,因此确定调用的是哪个具体类型的接口。
    • 重载:在编译之前就知道用哪个函数,即在一个类中有相同的函数名,重载函数的参数列表不同(参数个数,参数类型 或 参数顺序 三者中必须有一个不同);函数的返回类型可以相同也可以不相同仅仅返回类型不同不足以成为函数的重载
  • 运行时多态
    动态联编,通过继承虚函数来实现,也叫重写。

1.3 两种的优缺点?

运行期多态优点:OO设计中重要的特性,对客观世界直觉认识。
运行期多态缺点:

  • 运行期间进行虚函数绑定,提高了程序运行开销;
  • 虚表指针增大了对象体积,类也多了一张虚函数表。

编译期多态优点:在编译器完成多态,提高运行期效率
编译期多态缺点:无法实现模板的分离编译,当工程很大时,编译时间不可小觑。

1.4 虚函数的实现机制?虚表内存位置?

  • 虚函数是通过虚函数表虚指针来实现,通过索引在表中定位函数地址
  • 在有虚函数的类对象中,它内存空间的头部会有一个虚指针,指向要管理的虚函数表,而虚函数表包含了一个类(所有)的虚函数的地址。
  • 子类对象对父类虚函数进行重写的时候,虚函数表中相应虚函数地址会被从父类的改成子类的虚函数地址;而当我们用一个父类的指针来操作子类对象的时候,它就可以指明实际所调用的函数。
  • 虚表存在全局静态区,而 Linux/Unix 是生成的可执行文件的可读数据区中。

1.5 虚函数调用是在编译时确定还是运行时确定的?如何确定调用哪个函数?

  • 只有通过指针或者引用的方式调用虚函数是运行时确定,通过值调用的虚函数是编译期就可以确定。
  • 通过查找虚函数表中的函数地址确定。

1.6 虚函数是存在类中还是类对象中?

存在类中,不同的类对象共享一张虚函数表(为了节省内存空间)

1.7 在(基类的)构造函数和析构函数中调用虚函数会怎么样?

  • 构造函数不能为虚函数(构造顺序:父类->成员类->自身)
    • 存储空间角度,虚函数的调用需要虚函数表(vptr)指针,而该指针存放在对象的内存空间中,在构造函数中进行初始化工作,即初始化vptr,让它指向正确的虚函数表。所以需要调用构造函数才可以创建或初始化它的值,否则即使开辟了空间,该指针也为随机值;若构造函数声明为虚函数,那么由于对象还未创建,还没有内存空间,更没有虚函数表地址用来调用虚构造函数了
    • 多态角度,构造一个对象的时候,必须知道对象的实际类型;而虚函数主要是实现多态,在运行时才可以明确调用对象,根据传入的对象类型来调用函数。在调用构造函数时,由于对象还未构造成功。编译器无法知道对象的实际类型,是该类本身,还是该类的一个派生类,或是更深层次的派生类。并且构造函数的作用是提供初始化,在对象生命期仅仅运行一次,不是对象的动态行为,没有必要成为虚函数
  • 析构函数可以为虚函数(析构顺序:自身->成员类->父类)
    当以基类为指针变量创建子类时,如果析构函数不是虚函数,根据析构顺序,只有基类会被释放,子类并没有释放,存在内存泄漏的隐患。

1.8 C语言可以实现虚函数机制吗,如何实现?

  • 手动构造父子关系、创建虚函数表、设置虚表指针并指向虚函数表、填充虚函数表。
  • 当虚函数重写的时候还需要手动修改函数指针
posted @   bok_tech  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
  1. 1 翻云覆雨 BLL
  2. 2 与我无关 阿冗
  3. 3 想去海边 夏日入侵企划
  4. 4 没有理想的人不伤心 新裤子
  5. 5 生活因你而火热 新裤子
与我无关 - 阿冗
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.
点击右上角即可分享
微信分享提示