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

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

虚函数是一个使用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();
}


http://www.kler.cn/a/581716.html

相关文章:

  • Python之pyqt5生成计算机前端页面并运行
  • Android :实现登录功能的思路
  • selenium的鼠标操作
  • SpringBoot 统一异常处理
  • JavaScript(Web APIs)
  • springboot433-基于SpringBoot的流浪猫爱心救助系统(源码+数据库+纯前后端分离+部署讲解等)
  • 消防行业如何借助 TDengine 打造高效的数据监控与分析系统
  • Spring(七)AOP-代理模式
  • 【群晖 NAS】把微软bing的背景图自动更换为群晖DSM7.X登录界面和DSM欢迎信息的教程
  • 「 DelegateUI 」Ant-d 风格的 Qt Qml UI 套件
  • VMware虚拟机迁移失败的故障排查方法
  • 文献阅读 | Nature Methods | SCENIC: 单细胞调控网络推断和聚类
  • warning: remote HEAD refers to nonexistent ref, unable to checkout.
  • Oracle 数据库导出与导入操作指南
  • 后端面试高频笔试题(非常规LeetCode类型)
  • 2025最新群智能优化算法:基于RRT的优化器(RRT-based Optimizer,RRTO)求解23个经典函数测试集,MATLAB
  • LVDS系列3:Xilinx的IOBUFDS原语
  • 通过 ElasticSearch的Python API和`curl` 命令获取Elasticsearch 所有索引名称
  • OpenManus 的提示词
  • ubuntu挂载新硬盘