虚函数表剖析
来源:互联网 发布:无冬之夜2 mac 编辑:程序博客网 时间:2024/05/14 11:53
虚函数表的研究
有如下四个类定义:
class base
{
public:
virtual void fun1();
virtual void fun2();
virtual void fun3();
virtual void fun5();
};
class a:public base
{
public:
void fun1();
virtual void fun4();
};
class b:public base
{
public:
void fun1();
};
class d:public a
{
};
下面分析一下各类实例初始化时,虚函数表的结构。
有如下定义:
base vbase;
a va;
b vb;
d vd;
首先,这四个类是在一个继承链中,他们各有一个虚函数表(因为他们之中都存在虚函数)。
以下是各类实例的虚函数表地址:
vbase:0x0046f064(vbase的虚函数表占20字节)
Va:0x0046f078(va的虚函数表占24字节)
Vb:0x0046f090(vb的虚函数表占20字节)
Vd:0x0046f0a4(vd的虚函数表占24字节)
其次,虚函数表中的元素,都是函数指针,每个元素占4字节。
依次类推,vbase中有5个虚函数,va中有6个,vb中有5个,vd中有6个。
但是实际上的数量应该是,4、5、4、5。
为什么会引起这种现象,来看一下虚函数表中到底存了些什么数据,以下是实际结果,vc中截取:
Vbase:0x004010af、0x00401032、0x0040112c、0x004010a5、0x00000000
Va:0x00401190、0x00401032、0x0040112c、0x004010a5、0x00401186、0x00000000
Vb:0x0040118b、0x00401032、0x0040112c、0x004010a5、0x00000000
Vd:0x00401190、0x00401032、0x0040112c、0x004010a5、0x00401186、0x00000000
看一下这些值指向的是什么函数:
0x004010af:base::fun1()
0x00401032:base::fun2();
0x0040112c:base::fun3();
0x004010a5:base::fun5();
0x00401186:a::fun4();
0x00401190:a::fun1();
0x0040118b:b::fun1();
文字替换一下,很容易得出结论:
1、 每个类的虚函数表结尾会有一空元素,标示此表的结束。
2、 每个类都有一张独立的虚函数表
3、 子类继承父类,会新建一张虚函数表,并将父类的虚函数表拷贝过来。如果改写了虚函数,则将自己的表中元素相应改写,指向被改写的函数。
4、 类的多个实例会共享类的虚函数表。
例如:
base* b1 = new base();
base* b2 = new base();
base* b3 = new base();
b2和b3的虚函数表指针的值将于b1相同。
扩展: 看一下如下的实现: Base* pbase=new a; pbase->fun1(); 此时是以基类指针调用的fun1,如果fun1是普通函数,毫无疑问,应该调用base::fun1。但fun1为虚函数,存在于虚函数表中,在new a的时候,new的是a对象及其虚函数表,所以,调用的是a::fun1。这就是虚函数的妙用。 多重继承中,虚函数表的研究: 以上代码展示了一个简单的多重继承例子。 看一下实际内存数据: 2、MyIH有两张虚函数表,则它的头8个字节是虚函数表地址:2c 78 41 00 1c 78 41 00。 则两张表的实际地址为:0x0041782c和0x0041781c。 3、0x0041782c中的数据:49 12 41 00 58 12 41 00 00 00 00 00 分析得到: 0x00411249:b1f1的地址 0x00411258:b1f2的地址 0x00000000:结束标示符 4、0x0041781c中的数据:3c 10 41 00 2d 10 41 00 00 00 00 00 分析得到: 0x0041103c:b2f1的地址 0x0041102d:b2f2的地址 0x00000000:结束标示符 得出结论: 对于对象MyIH 1、有两张虚函数表,分别从base1和base2继承 2、两张表的顺序,遵循类定义中的继承先后顺序,即第一张表是继承于base1的,第二张表继承于base2
1、MyIH的内存首地址为0x0012ff50(通过监视&MyIH得到)
- 虚函数表剖析
- C++虚函数表剖析
- C++虚函数表剖析
- C++虚函数表剖析
- C++虚函数表剖析
- C++虚函数表剖析
- C++虚函数表剖析
- C++虚函数表剖析
- 虚函数表深度剖析
- C++虚函数表剖析
- C++虚函数表深入剖析
- C++虚函数表深入剖析
- C++虚函数表深入剖析
- C++虚函数表深入剖析
- C++ 虚函数 剖析
- 剖析虚函数
- 深度剖析C++虚函数
- 浅谈c++虚函数 虚继承的虚表剖析
- 动态创建的控件如何取得ClientID
- USACO :Hamming Codes 解题报告
- Irrlicht 关于vector3 getHorizonAngle()的作用
- 参加digi技术大会-物联网
- VS 技巧
- 虚函数表剖析
- hack命令2
- ruby类变量在development模式失效
- combobox相关处理
- IT新技术 云计算
- 如何使用C++制作WPF项目
- Mini2440 Ethernet KITL调试
- C#静态构造函数
- Irrlicht 的 IrrEdit 工作路径(workspack)的设置