- 论坛徽章:
- 0
|
本帖最后由 sampher 于 2013-09-29 09:28 编辑
我知道C++内存对象模型的基本知识,对于一个有virtual函数的类而言,实例的第一个size_t大小是指向虚表的指针。
因此我写了下面一个在vc下编译的小程序,是可以执行的。
这个类有3个函数,分别叫f/g/h,我不用类的方法调用,而是用指向虚表的实例头部来操作。
- class Father
- {
- public:
- int i;
- Father(){i=22;}
- virtual void f(){printf("f\n");}
- virtual void g(){printf("g\n");}
- virtual void h(){printf("h\n");}
- };
- typedef void (*pFather)(Father*);
- int main(int argc, char* argv[])
- {
- Father* pf=new Father;
- pFather *pVtable=*(pFather**)(pf);
- pVtable[0](pf);
- pVtable[1](pf);
- pVtable[2](pf);
- delete pf;
- return 0;
- }
复制代码 程序的输出是:到目前为止看起来一切正常。但是我如果把程序稍微改一下,就不能运行了。我发现pVtable[0](pf)在调用f函数的时候,在debug状态下观看f函数调用时的this指针,发现并不是pf。这个非常奇怪。如果我在函数f里面操作一个成员变量,那么打印出来的i的值是一个非常大的值例如17111262。如果我要操作i成员,例如++i,那么程序直接崩溃,像下面这样:
- class Father
- {
- public:
- int i;
- Father(){i=22;}
- virtual void f(){printf("f:%d\n",i);}//这一行打印的i是个无效值。
- virtual void g(){printf("g:%d\n",++i);}//++i导致崩溃。
- virtual void h(){printf("h\n");}
- };
- typedef void (*pFather)(Father*);
- int main(int argc, char* argv[])
- {
- Father* pf=new Father;
- pFather *pVtable=*(pFather**)(pf);
- pVtable[0](pf);
- pVtable[1](pf);
- pVtable[2](pf);
- delete pf;
- return 0;
- }
复制代码 这是为什么呢? pVtable在调用的时候,类的成员函数的第一个参数默认就是实例的指针对么?
那么上面改过以后的程序为什么this指针不对? 错在哪里? |
|