本文主要是介绍关于虚表和虚表指针,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
有关知识复习
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需要访问基类成员所需要偏移的字节数。
这篇关于关于虚表和虚表指针的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!