C++虚函数系列之一:统计class中虚函数的个数

来源:互联网 发布:医院网络调研报告 编辑:程序博客网 时间:2024/05/01 00:36

AuthorJeff   2005-12-2

关键字:C++ 虚函数 存储

环境:Window XP Professional + SP2, VC6.0

 

无论在栈中还是在堆中申请内存空间,项目组都会要求用memset()将申请到的空间清0。对于简单数据类型数组和结构简单的struct,classmemset()很好用。但是对于某些struct或者classmemset()之后程序会莫名其妙down掉,排起错误来很费力。最后发现用memset()0struct或者class,要么里面有虚函数,要么包含的成员对象有虚函数;memset()将空间清0,间接地将指向virtual table的指针清空。如果程序不down掉,那才奇怪呢!

 

下面看看class在栈中的存储情况。

class C001

{

public:

    C001() : ch(32), pos(1) { };

    virtual ~C001() { };

private:

    virtual void Display(void) {

        printf("display C002");

    }

public:

    virtual void Outp(int n) {

        printf("Number = %d/n" , n);

    }

   

private:

    int    pos;

    char  ch;

};

 

int  main(void)

{

    int     d = 0x1234;

   C001  c1;

   return  0;

}

(代码写的不好看,将就)

编译,Debug,看看变量在内存的存储情况。class内部成员变量按定义的先后顺序由低地址向高地址方向存储(与栈的增长方向相反)。而函数内部变量存储方向与class的相反,与栈的增长方向相同。

int  *p = (int *)&c1;

printf("*(p + 1) = %d/n", *(p + 1));   // value of pos

        printf("*(p + 2) = %d/n", (*(p + 2) & 0xff)); // value of ch

printf("*(p + 3) = 0x%08x/n", *(p + 3));  // value of d

class的第一个变量的前面存放不是CCCCCCCC(Debug版本),而是某个具体的值。这个值就是今后研究的重点,指向virtual table指针。class在栈中的情况大致如下:

(我的机器上virtual table位于常量存储区,有点怪怪的,不知道为什么?)

virtual table的第一个元素是C001::`scalar deleting destructor'(不知道如何称呼它)。在C001::`scalar deleting destructor'函数体内先调用C001::~C001(),再调用operator delete释放申请的内存空间。 virtual table的最后是00 00 00 00,表示virtual table的结束。有了这些,就可以计算class到底有多少个虚函数(包括继承来的)

    int    *p = (int *)&c1;

    int    *q;

    for (int i = 0; ; i++) {

        q = (int *)*((int *)(*p) + i);

        if (NULL == q) {

            printf("virtual function number = %d/n", i);

            break;

        }

    }

class C001来说,virtual function number = 3

原创粉丝点击