探索c++虚函数表
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了探索c++虚函数表相关的知识,希望对你有一定的参考价值。
c++中多态的实现
我们都知道,c++中的多态是在虚函数的基础上实现的,用指向派生类的基类指针调用派生类(或基类)中自己的成员函数。那么,具体是怎么实现的呢?
其实它是通过虚函数表来实现的,虚函数表是保存虚函数地址的一张表,若一个类中有虚函数,当程序运行时,编译器通过在虚函数表中查找相应的虚函数的地址来调用该函数。
对象的继承有如下几类:
1.单一继承
2.多重继承
3.重复继承(钻石继承)
4.虚继承
下面我们分别来看一下各种继承的内存布局:
单一继承
单一继承的结构
运行下面这段程序:
#include<iostream> using namespace std; typedef void(*PFUN)(); class B { public: B() :_b(0){} virtual void fun1() { cout << "B::fun1()" << endl; } virtual void fun2() { cout << "B::fun2()" << endl; } private: int _b; }; class D:public B { public: D() :_d(1){} void fun1() { cout << "D::fun1()" << endl; } virtual void fun3() { cout << "D::fun3()" << endl; } private: int _d; }; void PrintVT(int b)//根据虚函数表中的函数地址调用虚函数 { PFUN pfun = NULL; int *ptr = (int *)b; int i = 0; while (ptr[i]) { pfun = (PFUN)ptr[i];//将虚函数的地址转换为函数指针 pfun();//用函数指针调用函数 i++; } } int main() { D d; PrintVT(*(int *)&d);//取出虚函数表的地址 getchar(); return 0; }
我们在内存窗口可以看到:
上面程序的功能是调用虚函数表中函数的地址所对应的函数,程序运行结果如下:
现在我们可以知道单一继承的内存布局了
单一继承对象模型
单一继承的内存布局是:
1)对象的最前面放的是虚函数表的地址,然后根据继承的顺序依次放置成员变量的地址。
2)虚表里按继承顺序先放置派生类从基类继承来的虚函数的地址,然后是派生类自己的虚函数的地址。
3)满足覆盖条件的派生类的虚函数地址覆盖了基类虚函数的地址。
覆盖:
1)不同作用域(基类和派生类中)
2)函数名相同,参数列表相同,返回值类型相同(协变除外)
3)为虚函数(virtual)
注:协变是指基类虚函数返回值为基类类型的指针,派生类虚函数的返回值为派生类类型的指针
多重继承
未完待续。。。
以上是关于探索c++虚函数表的主要内容,如果未能解决你的问题,请参考以下文章
C++之多态总结(多态的定义及实现,抽象类,多态原理,单继承,多继承中的虚函数表)