关于虚表和虚表指针

    xiaoxiao2021-04-13  27

    有关知识复习

    1:动态多态 动态绑定:在程序执行期间(非编译期间)判断所引用对象的实际类型,根据其实际类型调用相应的方法。 2:动态多态具体实现、

    class A { public: virtual void funtest1() { cout << "A.funtest1" << endl; } virtual void funtest2() { cout << "A.funtest2 " << endl; } int _a; }; class B1 : public A { public: virtual void funtest1() { cout << "B1.funtest1" << endl; } virtual void funtest3() { cout << "B1.funtest3" << endl; } int _b1; }; void funtest(A &s) { s.funtest1(); s.funtest2(); } int main() { B1 b1; funtest(b1); system("pause"); return 0; }

    在funtest函数里面用基类的引用作为参数,真正传过去的是派生类的对象,而且在派生类里面是对funtest1函数进行了重写的,所以在执行期间会根据所引用的具体类型调用相应的函数。 3:虚表的简单查看

    #include<stdlib.h> #include<stdio.h> #include<iostream> using namespace std; class A { public: virtual void funtest1() { cout << "A.funtest1" << endl; } virtual void funtest2() { cout << "A.funtest2 " << endl; } int _a; }; class B1 : public A { public: virtual void funtest1() { cout << "B1.funtest1" << endl; } virtual void funtest3() { cout << "B1.funtest3" << endl; } int _b1; }; typedef void(*pvf)(); void Print() { B1 b1; b1._a = 1; b1._b1 = 2; pvf *fun = (pvf *)*(int*)&b1; while (*fun) { (*fun)(); fun++; } } void FunTest() { cout << sizeof(B1) << endl; } int main() { Print(); FunTest(); system("pause"); return 0; }

    通过求取B1类的大小可以在内存中查看b1的存储方式,图上所表示的是虚表指针指向的虚表和打印出来的虚表的实际对应.通过对b1对象内存的分析可以知道除了b1所含的两个整型意外,最上面的四个字节就是虚表指针,指向的虚表通过打印的方式显示出来如图中所示,由于B1对A类是公有继承而且在B1类中对基类的funtest1函数进行了重写,所以派生类B1的虚表就应该是图中所显示的内容。

    菱形虚拟继承中派生类的虚表指针以及偏移量指针

    class A { public: virtual void funtest1() { cout << "A.funtest1" << endl; } virtual void funtest2() { cout << "A.funtest2 " << endl; } int _a; }; class B1 :virtual public A { public: virtual void funtest1() { cout << "B1.funtest1" << endl; } virtual void funtest3() { cout << "B1.funtest3" << endl; } int _b1; }; class B2 :virtual public A { public: virtual void funtest2() { cout << "B2.funtest2" << endl; } virtual void funtest4() { cout << "B2.funtest4" << endl; } int _b2; }; class C :public B1, public B2 { public: virtual void funtest3() { cout << "C.funtest3" << endl; } virtual void funtest4() { cout << "C.funtest4" << endl; } virtual void funtest5() { cout << "C.funtest5" << endl; } int _c; }; typedef void(*pvf)(); void Print() { A a; /*c._a = 1; c._b1 = 2; c._b2 = 3; c._c = 4;*/ pvf *fun = (pvf *)*(int*)&a; while (*fun) { (*fun)(); fun++; } } void FunTest() { cout << sizeof(C) << endl; } int main() { Print(); FunTest(); system("pause"); return 0; }

    如图所示,就是C类对象在内存空间的具体存储,红色线所指函数或者数字即为C类对象中的指针所指内容,要么是偏移量大小,要么是虚表指针,特别之处在于两个 ‘-4’,表示的是从该位置向上偏移四个字节才是C通过这个继承体系继承的B1,B2 类在C中存储的起始位置。12和24就是偏移量大小,若C B1 B2需要访问基类成员所需要偏移的字节数。

    转载请注明原文地址: https://ju.6miu.com/read-668784.html

    最新回复(0)