当前位置: 首页 > news >正文

虚函数和虚表的原理是什么?

虚函数是一个使用virtual关键字声明的成员函数,在基类中声明虚函数,在子类中可以使用override重写该函数。虚函数根据指针或引用指向的实际对象调用,实现运行时的多态。

虚函数表(虚表)是一个用于存储虚函数地址的数组,每个包含 虚函数的类都存在一个虚函数表,编译器会为每一个包含虚函数的类分配一根虚函数指针(vptr),虚函数指针指向虚函数表,在运行时会根据虚函数指针找到虚函数表,然后根据虚函数的索引找到该虚函数的地址,然后调用函数。虚函数表之中的虚函数是按照类之中的虚函数的顺序排列的。当对象初始化时,虚指针会被初始化指向该类的虚函数表。

在C++之中虚函数使用virtual关键字声明,重写该方法是可以使用override显式地声明重写该虚方法,但是在C#之中是强制要求书写override重写方法的。

在C++之中由于虚函数的调用主要操控虚指针找到虚函数表对虚函数进行操作的,这一操作相对比较直接,所以性能较高,特别是对于一些性能要求比较高的场景之中。而在C#之中,虚函数的调用由托管空间管理,性能比较低,但是这种性能差异在场景之中并不明显。

在C++之中存在多继承,虚函数的实现就较为复杂,可能涉及多个虚函数表和虚函数指针,但是在C#之中不存在多继承,但是可以多继承接口,由于接口只是声明了方法而没有实现方法体,类实现接口时也会基于运行时多态决定实现类的哪个接口方法,所以C#之中的虚函数与接口的机制是并非完全独立的。在C++之中不存在默认的虚函数,在C#之中也不存在默认的虚函数,但是如果C#中的类被声明成abstract,那么该抽象类之中的抽象方法默认都被认为是虚的,需要在子类中进行重写,不过抽象类中也可以存在非抽象的,非虚的,以及非抽象虚的方法。

举例:

#include<iostream>
using namespace std;

class TestBase{
	public:
		virtual void Speak(){
			cout<<"TestBase"<<endl;
		}
};

class Test:public TestBase{
	public:
		void Speak()override{
			cout<<"Test"<<endl;
		}
};

int main(){
	Test test;
	TestBase* testBase=&test;
	testBase->Speak();
}

相关文章:

  • Deepseek中的MoE架构的改造:动态可变参数激活的MoE混合专家架构(DVPA-MoE)的考虑
  • 【算法day5】最长回文子串——马拉车算法
  • 静态网页的爬虫(以电影天堂为例)
  • Git学习笔记(二)
  • 大白话react第十八章React 与 WebGL 项目的高级拓展与优化
  • Unity之如何实现哔哩哔哩直播弹幕游戏
  • docker本地部署RagFlow
  • Java集合框架全解析:从数据结构到高并发简单解析
  • 技术周总结 03.03 - 03.09 周日(Java监控 SpringAI)
  • PY32MD320单片机 QFN32封装,内置多功能三相 NN 型预驱。
  • 在github action工作流使用nw和nw-builder打包
  • 读书报告」网络安全防御实战--蓝军武器库
  • 【jstack查询线程信息】1.对比下arthas的thread 和jvm指令
  • linux下 jq 截取json文件信息
  • 前端数据模拟利器 Mock.js 深度解析
  • Etcd学习笔记
  • 通过一篇文章让你稳过计算机二级(C语言)
  • 为wordpress自定义一个留言表单并可以在后台进行管理的实现方法
  • 火语言RPA--指定PDF页另存为图片
  • Redis客户端
  • 终于,俄罗斯和乌克兰谈上了
  • 白玉兰奖征片综述丨海外剧创作趋势观察:跨界·融变·共生
  • 媒体:中国女排前队长朱婷妹妹被保送浙大受质疑,多方回应
  • 外交部介绍对巴西、阿根廷、智利、秘鲁、乌拉圭等5国试行免签政策
  • 文化润疆|为新疆青少年提供科普大餐,“小小博物家(喀什版)”启动
  • 秦洪看盘|指标股发力,A股渐有突破态势