现在的位置: 首页 > 综合 > 正文

C++虚表探究

2014年01月24日 ⁄ 综合 ⁄ 共 1491字 ⁄ 字号 评论关闭

下午闲来没事,在2005下面探究了一下C++的虚表模型。总结如下:

1. 对相同的同一个class 创建多个object,可以发现 vfptr是指向同一个地址,
   可见一个class 维护一个虚表,与创建对象没有关系

2. 如果一个基类(没有通过继承创建)含有virtual 函数,则这个这个类会
 额外产生一个虚表,其大小是其成员变量,加上一个函数指针的大小。

3.  虚表的作用用来实现多态, 其最终的原理是基类可以透明的通过vfptr[index]
 来访问成员函数,这就意味着同一个继承里面的class群,其vfptr每个index
 对应的函数是相同的。

4.  vfptr的开始的地址用来存放函数指针,后面部分用来存放RTTI信息

5. 派生类的构造过程:
 1.构造基类,此时this 指针指向的vfptr是基类的vfptr
 2.构造派生类,vfptr的地址转移到派生类的vfptr
 这意味着,在构造函数期间,无法实现本Class体系的多态的行为

6. 析构的过程和构造一样,会存在vfptr转换的情况

7. 基类的析构函数如果不是virtual 的会导致基类无法析构
 此外还有更严重的问题:
 如果基类没有虚函数,其则不会产vfptr,此时如果派生有虚函数,
 则派生类会产生vfptr,这样会导致赋值异常.

 Derive* pDerive = new Derive();
 Base *pTestBase  = pDerive;
 
 例如本例中,最终pTestBase 和 pDerive是不等的
 pDerive = 0x003A4F58
 pTestBase = 0x003A4F5C
 
 其内存镜像为
 0x003A4F58  40 67 41 00 
 0x003A4F5C  01 00 00 00 
 0x003A4F60  02 00 00 00 
 0x003A4F64  03 00 00 00 
 
 pDerive 的tihs 指针指向虚表
 而pTestBase没有虚表,会指向第一个元素

#include <cstdio>
#include <iostream>

#define TRACE() printf("%s/r/n",__FUNCTION__);

class Base
{
public:
 Base()
 {
  TRACE();
  m_1 = 1;
  m_2 = 2;
  m_3 = 3;
 }

 /*virtual*/ ~Base()
 {
  TRACE();
 }

 //virtual void Fun1()
 //{
 // TRACE();
 //}
 //virtual void Fun2()
 //{
 // TRACE();
 //}
 //virtual void Fun3()
 //{
 // TRACE();
 //}

private:
 int m_1;
 int m_2;
 int m_3;
};

class Derive :public Base
{
public:

 Derive()
 {
  TRACE();
 };
 /*virtual*/ ~Derive()
 {
  TRACE();
 };

 void virtual Testfun()
 {

 }
};

int main()
{
 //Base*  pDerive = new Derive();
 Derive* pDerive = new Derive();
 Base *pTestBase  = pDerive;

 printf("This : 0x%08x  vptr :0x%08x/r/n",pDerive,((int *)pDerive)[0]);
 printf("This : 0x%08x  vptr :0x%08x/r/n",pTestBase,((int *)pTestBase)[0]);
 
 delete pTestBase;
}

 

抱歉!评论已关闭.