首页 > 学院 > 开发设计 > 正文

探究多态&虚表

2019-11-08 18:38:39
字体:
来源:转载
供稿:网友

多态

所谓多态,就是当使用基类的指针或引用调用重写的虚函数时,当指向父类调用的就是父类的虚函数,指向子类调用的就是子类的虚函数。 下面来通过代码来理解多态的含义

class AA{public: virtual void fun() { cout << "AA::fun()" << endl; }};class BB : public AA{public: virtual void fun() { cout << "BB::fun()" << endl; }};void FUN(AA& a){ a.fun();}void Test1(){ AA a; BB b; FUN(a); FUN(b);}

结果为: AA::fun() BB::fun() C++的多态分为静态多态动态多态静态多态:静态多态就是重载,因为是在编译期决议确定。也就是在编译的时候就能确定函数的地址。 动态多态:是通过继承重写基类的虚函数实现的多态,在运行期间决议确定。也就是编译期间不知道函数的地址,只知道存储函数地址的虚表的地址。 C++中多态的实现就是通过虚函数实现的,虚函数的对象实例中都存在一张虚函数表。

虚函数表

虚函数表是通过一块连续内存来存储虚函数的地址,指明了实际调用的虚函数指针。

class AA{public: virtual void fun1() {} virtual void fun2() {}PRotected: int _a;};void Test2(){ AA a;}

这里写图片描述 通过监视窗口可以看到,对象a的首部存储了一个地址,指向的空间存储了虚函数的地址,称为虚函数表。所以sizeof(a)的值为8。

【含有虚函数的单继承对象模型】

typedef void(*FUNC) ();class AA{public: virtual void fun1() { cout << "AA::fun1()" << endl; } virtual void fun2() { cout << "AA::fun2()" << endl; }protected: int _a;};class BB : public AA{public: virtual void fun1() { cout << "BB::fun1()" << endl; } virtual void fun3() { cout << "BB::fun3()" << endl; }protected: int _b;};void PrintfVTable(int *VTable){ cout << "虚表地址:" << "0x" << VTable << endl; for (int i = 0; VTable[i] != 0; ++i) { cout <<"虚函数地址:0x"<< VTable[i] << " "; FUNC f = (FUNC)VTable[i]; f(); } cout << endl;}void Test3(){ AA a; BB b; int* VTable1 = (int *)(*(int *)&a); int* VTable2 = (int *)(*(int *)&b); PrintfVTable(VTable1); PrintfVTable(VTable2);}

通过这种方式,可以依次打印出虚表地址以及虚函数的地址,结果如下: 这里写图片描述 这里写图片描述 虚表后面的0标志着虚表结束,类似于字符串结束符“/0”。

提示:若在windows平台vs下,程序出现异常中断,可以“清理解决方案”,这是由于编译器的小bug,没有在虚表最后加上0,出现死循环。

【含有虚函数的多继承对象模型】

typedef void(*FUNC) ();class AA1{public: virtual void fun1() { cout << "AA1::fun1()" << endl; } virtual void fun2() { cout << "AA1::fun2()" << endl; }protected: int _a1;};class AA2{public: virtual void fun1() { cout << "AA2::fun1()" << endl; } virtual void fun2() { cout << "AA2::fun2()" << endl; }protected: int _a2;};class BB : public AA1,public AA2{public: virtual void fun1() { cout << "BB::fun1()" << endl; } virtual void fun3() { cout << "BB::fun3()" << endl; }protected: int _b;};void PrintfVTable(int *VTable){ cout << "虚表地址:" << "0x" << VTable << endl; for (int i = 0; VTable[i] != 0; ++i) { cout <<"虚函数地址:0x"<< VTable[i] << " "; FUNC f = (FUNC)VTable[i]; f(); } cout << endl;}void Test4(){ BB b; int* VTable = (int *)(*(int *)&b); PrintfVTable(VTable); VTable = (int *)(*((int*)&b + sizeof (AA1) / 4)); PrintfVTable(VTable);}

这里写图片描述 这里写图片描述


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表