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

编程入门 行业动态 更新时间:2024-10-23 04:34:08

多态 虚函数表深度剖析 纯<a href=https://www.elefans.com/category/jswz/34/1767986.html style=干货讲解(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;
}

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

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

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

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

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

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;
}

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

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

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

 

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

比葫芦画瓢打印一下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)

本文发布于:2023-11-16 12:44:49,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1622494.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:干货   函数   深度   多态

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!