众所周知,虚拟地址空间划分成了好几个部分,有堆区、栈区、常量区、静态区......
(500条消息) C/C++代码内存分布图_程序分布图_橙予清的zzz~的博客-CSDN博客https://blog.csdn.net/weixin_69283129/article/details/126122989大家可以看这篇文章深入了解我们日常所写的C++代码都分布到了内存的哪些地方。
我们可以模拟创建指向堆区空间、指向栈区空间的地址、创建存在于静态区和常量区的变量或常量,通过获取它们的地址就可以判断出虚表地址的大致位置到底处在内存的那一部分了。
试验案例:
class A {
virtual void Func1() {
cout << "A:Func1()" << endl;
}
virtual void Func2() {
cout << "A:Func2()" << endl;
}
};
class B :public A {
virtual void Func1() {
cout << "B:Func1()" << endl;
}
virtual void Func3() {
cout << "A:Func()" << endl;
}
};
int main() {
int i = 10;
cout << "栈区:" << &i << endl;
int* p = new int;
cout << "堆区:" << &p << endl;
const char* str = "hello bit!";
cout << "代码区/常量区:" << &str << endl;
static double d = 3.14;
cout << "静态区:" << &d << endl;
A a;
cout << "父类对象a1虚表地址:" << (void*)(*(int*)&a) << endl;
}
代码解析:
倒数第三行中,a是父类A的对象,&a就表示对象a的地址,因为对象a中有虚函数Func1()和Func2(),那么就有相应的虚表指针vfptr,而且虚表指针默认是类对象的第一个成员,且指针大小一般是4字节,使用int*(4字节)就可以提取出对象a的vfptr地址(4字节),之后解引用就是vfptr,因为目前vfptr是int*,需要转换为16进制的地址,需要转换为void* ,这样就可以计算出虚表指针指向的虚表的地址了!
运行结果:
从结果可知:虚表地址和常量区的地址最为接近,可以表面虚表地址是存在于常量区的位置中的。