类的public成员函数的初始化及使用问题
class A
{
public:
A(){printf( "create\n ");};
~A(){printf( "destory\n ");};
virtual int func1(){printf( "In func1\n ");return 2;};
int func2(){printf( "In func2\n ");return 3;};
public:
char name;
};
void main()
{
char * p = NULL;
((A*)p)-> func2();
((A*)p)-> func1();
}
在上面的代码中,p-> func2()可以执行, 但p-> func1()会出错。 从生成的ASM code看, 在调用func2时,VC2005可以其函数地址,所以能够执行,而func1时,因为vtbl为非法值,所以报错。
我的问题是,谁能解释一下类中的pulbic 函数为什么可以这么使用。
[解决办法]
去看《深度探索C++对象模型》
和public不public没关系,你这个纯属幸运。
[解决办法]
int func2(){printf( "In func2\n ");return 3;};
这两个函数都没有使用成员变量,
A* p=0;
p-> func2()总是会成功的
[解决办法]
lz,你的理解还是有点不清晰,是这样的
为了讲解,我重新写了个例子
struct TEST
{
int date;
void fun2() {
date = 100;
}
virtual void fun1()
{
}
};
1)
fun2 是个普通的成员函数,当你调用fun2的时候
编译器是不会检查fun2内部是否访问了成员变量的,比如
TEST* p = 0;
p-> fun2();
编译可以通过,只是运行的时候出错了,因为this指针为空
在函数内部通过偏移量来找date成员变量的时候,访问了非法地址
fun2内的 date = 100; 汇编代码如下
00401083 mov eax,dword ptr [this]
00401086 mov dword ptr [eax+4],64h
看到了吗 [eax+4] 这个就是date成员变量的地址,通过this偏移4
得到(因为vftable指针占了4字节,所以第一个变量偏移4)
运行到这里的时候 this 为空,所以是 0, 0 + 4 = 4
程序去访问地址 4,当然这个是非法的地址,所以程序挂掉
2)
当你调用 fun1() 的时候,
TEST* p = 0;
p-> fun1();
fun1() 是个虚函数,因此许通过虚表(vftabe)去找到这个函数地址
你可以把vftabe的指针看做是TEST的第一个成员变量,
需要同过这个变量去找到响应的vftable,这个成员变量的偏移值为 0
这样就相当访问了类的一个
成员变量,如同上面的1)this 指针为空,当然所以就出现了访问非法地址
的运行错误
这是调用fun1相应的汇编码
TEST* p = 0;
0040101E mov dword ptr [p],0
p-> fun1();
00401025 mov eax,dword ptr [p] // 这里[p] 0 ,所以 edx 为 0
00401028 mov edx,dword ptr [eax] // [eax] 等于 [0],访问0地址,当然非法咯
..........
..........