【C/C++】虚函数调用流程 | 虚函数和一般函数的区别

创作不易,本篇文章如果帮助到了你,还请点赞 关注支持一下♡><)!!
主页专栏有更多知识,如有疑问欢迎大家指正讨论,共同进步!
c++系列专栏:C/C++零基础到精通

给大家跳段街舞感谢支持!ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ

c语言内容:

专栏:c语言之路重点知识整合

【c语言】全部知识点总结


目录

  • 一、虚函数的调用流程
    • 模仿_vfptr手动实现多态
  • 二、虚函数和一般函数的区别

一、虚函数的调用流程

在定义了虚函数的类中,类的最开始部分是一个虚函数表的指针——虚函数指针

在这里插入图片描述

虚函数指向一个虚函数表,表中存放了虚函数的地址,实际的虚函数存放在代码段中。

当子类继承了父类的时候也会继承父类的虚函数表,当子类重写父类中虚函数的时候,会将继承到虚函数表中的地址替换为重写的函数地址。这个过程称为覆盖

虚函数列表中,在重写虚函数的后面是父类未重写的虚函数,然后是子类虚函数

以上的过程将在编译阶段进行

【C/C++】虚函数调用流程 | 虚函数和一般函数的区别_第1张图片

_vfptr指向虚函数列表,通过对虚函数列表中的函数取址执行就能实现多态

模仿_vfptr手动实现多态

在类中定义两个虚函数:

class CTest 
{
public:
	virtual void fun(){ cout << "virtual void fun()" << endl; }
	virtual void fun2() { cout << "virtual void fun2()" << endl; }
};

在主函数中定义一个对象,并定义一个父类指针指向这个对象

	CTest tst;
	CTest* ptst = nullptr;
	ptst = &tst;

首先实现虚函数指针的描述:

由于虚函数指针vfptr处于对象的内存最前面,并且占用4字节

通过解引用取得对象内存首地址的vfptr

	*(int*)ptst 

通过vfptr指针间接引用到虚函数列表vftable

将 ptst 所指向的内存中的值视为一个整数

	(int*) (*(int*)ptst) [0]

再视为一个指向函数的指针,赋值给 p_fun1

	typedef void (*P_FUN)();
	P_FUN p_fun1 = (P_FUN)((int*)(*(int*)&tst))[0];

完整调用流程:

	typedef void (*P_FUN)();

	P_FUN p_fun1 = (P_FUN)((int*)(*(int*)&tst))[0];
	P_FUN p_fun2 = (P_FUN)((int*)(*(int*)&tst))[1];
	(*p_fun1)();
	(*p_fun2)();

【C/C++】虚函数调用流程 | 虚函数和一般函数的区别_第2张图片

【C/C++】虚函数调用流程 | 虚函数和一般函数的区别_第3张图片

二、虚函数和一般函数的区别

  • 调用流程不同:虚函数通过虚函数指针间接引用,普通函数可以使用函数名直接调用
  • 调用效率不同:虚函数调用流程复杂,效率低,普通函数效率高
  • 使用场景不同:虚函数的目的是为了实现多态

使用了虚函数,会增加访问内存开销,降低效率。


大家的点赞、收藏、关注将是我更新的最大动力! 欢迎留言或私信建议或问题。
大家的支持和反馈对我来说意义重大,我会继续不断努力提供有价值的内容!如果本文哪里有错误的地方还请大家多多指出(●'◡'●)

你可能感兴趣的:(C/C++,c语言,c++,开发语言,笔记,学习)