多态 虚函数表深度剖析 纯干货讲解(2)

这篇具有很好参考价值的文章主要介绍了多态 虚函数表深度剖析 纯干货讲解(2)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

💯 博客内容:多态

😀 作  者:陈大大陈

🚀 个人简介:一个正在努力学技术的准C++后端工程师,专注基础和实战分享 ,欢迎私信!

💖 欢迎大家:这里是CSDN,我总结知识和写笔记的地方,喜欢的话请三连,有问题请私信 😘 😘 😘

目录

虚函数存在哪里? 

虚函数的地址一定会被放进虚函数表吗?

结论 


 

虚函数储存在哪里? 

 首先思考一个问题,虚函数存在哪里?

虚函数和普通函数一样,存在代码段,同时将虚函数地址存了一份到虚函数表。

那虚函数表存在哪里?

存在栈区出了作用域会销毁,堆区需要动态分配内存,都不现实。

经过测试,虚表是储存在常量区的代码段的,跟常量很接近。

虚函数的地址一定会被放进虚函数表吗?

第二个问题,虚函数的地址一定会被放进虚函数表吗?

#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
class Base {
public:
	virtual void func1() { cout << "Base::func1" << endl; }
	virtual void func2() { cout << "Base::func2" << endl; }
private:
	int a;
};

class Derive :public Base {
public:
	virtual void func1() { cout << "Derive::func1" << endl; }
	virtual void func3() { cout << "Derive::func3" << endl; }
	virtual void func4() { cout << "Derive::func4" << endl; }
	void func5() { cout << "Derive::func5" << endl; }
private:
	int b;
};

class X :public Derive {
public:
	virtual void func3() { cout << "X::func3" << endl; }
};

int main()
{
	Base b;
	Derive d;
	X x;

	Derive* p = &d;
	p->func3();

	p = &x;
	p->func3();

	return 0;
}

多态 虚函数表深度剖析 纯干货讲解(2),C语言初阶以及进阶内容专栏,jvm,c++,开发语言,算法,数据结构,c语言

如图,这种情况三个虚表指针都没有存储func3的地址。 

难道是func3的地址没有存储吗?
并不是这样,监视窗口看到的内容是经过编译器处理的。

我们合理怀疑编译器骗我们。

多态 虚函数表深度剖析 纯干货讲解(2),C语言初阶以及进阶内容专栏,jvm,c++,开发语言,算法,数据结构,c语言

打开内存监视窗口,我们高度怀疑后面两个地址是被隐藏的两个虚函数的地址。 

虚表储存在类的前四个字节,我们就取这四个字节打印出来。

typedef void (*VFUNC) ();
void PrintVFT(VFUNC a[])
{
	for (size_t i = 0; a[i] != 0; i++)
	{
		printf("[%d]:%p\n", i, a[i]);
	}
	cout << endl;
}
int main()
{
	//void (*f)();
	VFUNC f2;
	Base b;
	PrintVFT((VFUNC*)(*((int*)&b)));
	return 0;
}

多态 虚函数表深度剖析 纯干货讲解(2),C语言初阶以及进阶内容专栏,jvm,c++,开发语言,算法,数据结构,c语言

看不明白的老铁可以看看上面的图。 

传入base类打印,结果如下。

多态 虚函数表深度剖析 纯干货讲解(2),C语言初阶以及进阶内容专栏,jvm,c++,开发语言,算法,数据结构,c语言

不对劲,清理解决方案之后再重新生成解决方案,再次编译。

 多态 虚函数表深度剖析 纯干货讲解(2),C语言初阶以及进阶内容专栏,jvm,c++,开发语言,算法,数据结构,c语言

第一次编译器出了bug,没有在虚表后标识上0,第二次就好了。 

多态 虚函数表深度剖析 纯干货讲解(2),C语言初阶以及进阶内容专栏,jvm,c++,开发语言,算法,数据结构,c语言

比葫芦画瓢打印一下d和x,但是此时仍然不能确定。 

终于到了放终结技的时候了,我们可以在打印的时候同时调用函数。

上面我们埋下了伏笔,在命令行窗口会打印出来调用函数的信息。

#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
class Base {
public:
	virtual void func1() { cout << "Base::func1" << endl; }
	virtual void func2() { cout << "Base::func2" << endl; }
private:
	int a;
};

class Derive :public Base {
public:
	virtual void func1() { cout << "Derive::func1" << endl; }
	virtual void func3() { cout << "Derive::func3" << endl; }
	virtual void func4() { cout << "Derive::func4" << endl; }
	void func5() { cout << "Derive::func5" << endl; }
private:
	int b;
};

class X :public Derive {
public:
	virtual void func3() { cout << "X::func3" << endl; }
};

//int main()
//{
//	Base b;
//	Derive d;
//	X x;
//
//	Derive* p = &d;
//	p->func3();
//
//	p = &x;
//	p->func3();
//
//	return 0;
//}
typedef void (*VFUNC) ();
void PrintVFT(VFUNC *a)
{
	for (size_t i = 0; a[i] != 0; i++)
	{
		printf("[%d]:%p\n", i, a[i]);
		VFUNC f = a[i];
		f();
	}
	cout << endl;
}
int main()
{
	//void (*f)();
	VFUNC f2;
	Base b;
	Derive d;
	X x;
	PrintVFT((VFUNC*)(*((int*)&b)));
	PrintVFT((VFUNC*)(*((int*)&d)));
	PrintVFT((VFUNC*)(*((int*)&x)));
	return 0;
}

运行结果如下。

多态 虚函数表深度剖析 纯干货讲解(2),C语言初阶以及进阶内容专栏,jvm,c++,开发语言,算法,数据结构,c语言

结论 

可算对上了捏!

 此时此刻,我们终于可以骄傲地回答上面的问题!

所有的虚函数都会被放进虚表吗?

是的!文章来源地址https://www.toymoban.com/news/detail-743642.html

到了这里,关于多态 虚函数表深度剖析 纯干货讲解(2)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C语言】指针的进阶(二)—— 回调函数的讲解以及qsort函数的使用方式

    目录 1、函数指针数组 1.1、函数指针数组是什么?  1.2、函数指针数组的用途:转移表 2、扩展:指向函数指针的数组的指针 3、回调函数 3.1、回调函数介绍  3.2、回调函数的案例:qsort函数 3.2.1、回顾冒泡排序  3.2.1、什么是qsort函数? 函数指针数组 是什么?首先主语是 数

    2024年02月07日
    浏览(44)
  • C语言中usleep与nanosleep函数讲解以及毫秒级休眠实现

    我们一般接触比较多的就是sleep函数了,这个的话就不用多说了,大家都知道。我们来介绍一下usleep以及nanosleep函数。 (1)函数讲解 为什么先介绍nanosleep函数呢?这是因为后面讲到的usleep函数中微妙级的实现是根据nanosleep函数实现的。 函数名称的 nano 是纳米、纳秒等计量单

    2024年02月08日
    浏览(34)
  • 【从JVM看Java,三问继承和多态,是什么?为什么?怎么做?深度剖析JVM的工作原理】

    《计算机底层原理专栏》:欢迎大家订阅学习,能够帮助到各位就是对我最大的鼓励! 文章目录 系列文章目录 前言 一、JVM是什么 二、 什么是继承 三、 什么是多态 总结         这篇文章聚焦JVM的实现原理,我更专注于从一个语言的底层原理,去剖析他的语法所实现的意义

    2024年02月05日
    浏览(55)
  • 【C++】 为什么多继承子类重写的父类的虚函数地址不同?『 多态调用汇编剖析』

    👀 樊梓慕: 个人主页  🎥 个人专栏: 《C语言》 《数据结构》 《蓝桥杯试题》 《LeetCode刷题笔记》 《实训项目》 《C++》 《Linux》《算法》 🌝 每一个不曾起舞的日子,都是对生命的辜负 本篇文章主要是为了解答有关多态的那篇文章那块的一个奇怪现象,大家还记得这张

    2024年02月19日
    浏览(38)
  • [C++]:万字超详细讲解多态以及多态的实现原理(面试的必考的c++考点)

    文章目录 前言 一、多态的定义及实现 1.多态的构成条件 2.c++11的override和final 3.重载,重写,重定义的比较 4.抽象类 5.多态的原理 6.多继承中的虚函数表 7.动态绑定和静态绑定 总结 多态的概念: 多态的概念:通俗来说,就是多种形态, 具体点就是去完成某个行为,当不同的

    2023年04月22日
    浏览(62)
  • 【初阶C语言】初阶结构体详细讲解

    结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。 例如描述一个学生: 结构的成员可以是标量、数组、指针,甚至是其他结构体。 有了结构体类型,那如何定义变量,其实很简单。 结构体变量访问成员 结构变量的成员是通过点操作符(

    2023年04月12日
    浏览(39)
  • 【C语言】初阶测试 (带讲解)

      目录 ① 选择题         1. 下列程序执行后,输出的结果为( ) 2. 以下程序的输出结果是?  3. 下面的代码段中,执行之后 i 和 j 的值是什么()  4. 以下程序的k最终值是: 5. 以下程序的最终的输出结果为: 6. 下列描述中正确的是()  7.C 语言规定,在一个源程序中,

    2024年02月09日
    浏览(35)
  • 【初阶C语言】实现扫雷(详细讲解+全部源码)

    本游戏用到了三个文件 两个源文件:扫雷.c ,game.c 一个头文件:game.h 想要做好游戏,首要任务就是要把模块想好。 先打印一个游戏菜单 玩家选择是否(1\\0)是否进入游戏 游戏思路:(这次实现的是初级难度的扫雷,棋盘9X9,10个雷) 我们先创建两个二维数组,一个数组布

    2023年04月09日
    浏览(36)
  • JavaScript 深度剖析-函数式编程(一)

    为什么要学习函数编程以及什么是函数式编程 函数式编程的特性(纯函数、柯里化、函数组合等) 函数式编程的应用场景 函数式编程库 Lodash 函数式编程是非常古老的一个概念,早于第一台计算机的诞生,函数式编程的历史。 那我们为什么现在还要学函数式编程? 函数式编程

    2024年02月15日
    浏览(47)
  • 你真的理解qsort函数吗?带你深度剖析qsort函数

    魔王的介绍:😶‍🌫️一名双非本科大一小白。 魔王的目标:🤯努力赶上周围卷王的脚步。 魔王的主页:🔥大魔王不哭 我们初识C语言时,会做过让一个整型数组按照从小到大来排序的问题,我们使用的是冒泡排序法,但是如果我们想要比较其他类型怎么办呢,显然我们

    2023年04月24日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包