一个对象指针没分配内存可以访问类的成员函数的问题

jtq 2005-12-08 04:23:47
程序如下:
#include <iostream.h>
class A
{
public:
void func()
{
int a = 5;
cout << a << endl;
}
int b;
};
void main()
{
A* pa = NULL;
pa->func();
}
这个程序运行没出现问题,pa没分配内存也可以调用类的成员函数?
无意中碰到这种情况,以前从来没这样用过。
请高手指点其中深层次原理。
...全文
377 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
Torch009 2005-12-09
  • 打赏
  • 举报
回复
说得都对。看个人的理解了。
wohow 2005-12-09
  • 打赏
  • 举报
回复
to lzzqqq(Jonersen)
pa->func()中没有访问类的成员,所以保证一定能运行
wohow 2005-12-09
  • 打赏
  • 举报
回复
如果在成员函数中访问类的成员,就要通过this,楼主可以自己验证一下。
虚函数要通过虚函数表vtable来调用,访问vtable就要访问this指针,所以没有初始化的this不能调用虚函数
lzzqqq 2005-12-09
  • 打赏
  • 举报
回复
A* pa = NULL;
pa->func();//<---虽然暂时没出错,但访问的是无效的函数地址!!!虽然编译通过,但不保证总能运行.
wohow 2005-12-09
  • 打赏
  • 举报
回复
编译下面的代码成汇编:
class A
{
int b;
public:
int func();
};
int A::func()
{
int a = 5;
++a;
return a;
}
int func(A *const p)
{
int a = 4;
return --a;
}
void f()
{
A *x = 0;
x->func();
func(x);
}
汇编结果:(其中不相干不分用...代替)
...
@A@func$qv segment virtual
@@A@func$qv proc near
?live16385@0:
;
; int A::func()
;
push ebp
mov ebp,esp
;
; {
; int a = 5;
;
@1:
mov eax,5
;
; ++a;
;
?live16385@32: ; EAX = a
inc eax
;
; return a;
;
;
; }
;
?live16385@64: ;
@3:
@2:
pop ebp
ret
@@A@func$qv endp
@A@func$qv ends
...
@func$qxp1A segment virtual
@@func$qxp1A proc near
?live16386@0:
;
; int func(A *const p)
;
push ebp
mov ebp,esp
;
; {
; int a = 4;
;
@4:
mov eax,4
;
; return --a;
;
?live16386@32: ; EAX = a
dec eax
;
; }
;
?live16386@48: ;
@6:
@5:
pop ebp
ret
@@func$qxp1A endp
@func$qxp1A ends
...
@f$qv segment virtual
@@f$qv proc near
?live16387@0:
;
; void f()
;
push ebp
mov ebp,esp
push ebx
;
; {
; A *x = 0;
;
@7:
xor ebx,ebx
;
; x->func();
;
?live16387@32: ; EBX = x
push ebx
call @@A@func$qv
pop ecx
;
; func(x);
;
push ebx
call @@func$qxp1A
pop ecx
;
; }
;
?live16387@64: ;
@8:
pop ebx
pop ebp
ret
@@f$qv endp
@f$qv ends
...

关键看f()中两个函数调用,都是push ebx(把参数压入堆栈),然后调用函数。
因为A::func()和func(A *const p)是不同的函数,所以汇编函数名也不同。
从调用过程看,调用x->func()和调用func(x)是类似的,完全印证了本人前面的观点
faller20002003 2005-12-09
  • 打赏
  • 举报
回复
to wohow:
访问虚函数表不是通过this指针,而是通过一个指向虚函数表的指针vptr,你可以用sizeof(A)看看class A的大小。
jtq 2005-12-08
  • 打赏
  • 举报
回复
呵呵
felllove 2005-12-08
  • 打赏
  • 举报
回复
ding``````似乎都有道理``
菜牛 2005-12-08
  • 打赏
  • 举报
回复
一个类所有的对象实例共享同样的成员函数,每个对象实例的成员函数本质上是一个函数指针,可以看看这个函数指针的数值,应该指向同一个地址。也就是说,这个函数体在程序中只有一份。
faller20002003 2005-12-08
  • 打赏
  • 举报
回复
虚函数是通过vtable访问的。每个类都有一个指向虚函数表的指针作为自己的成员变量,不创建对象就无法访问虚函数表。我认为是这样的。
jtq 2005-12-08
  • 打赏
  • 举报
回复
楼上,为什么把func()声明为virtual运行就出错?
难道还有其他解释
jtq 2005-12-08
  • 打赏
  • 举报
回复
不行
为什么
cunsh 2005-12-08
  • 打赏
  • 举报
回复
呵呵.
你试试把func()声明为virtual的看看.
jtq 2005-12-08
  • 打赏
  • 举报
回复
有点魄力和地狱天使说的有道理
cky41 2005-12-08
  • 打赏
  • 举报
回复
可能是吧,唉,不想了,只是语言的实现机制嘛
huofen2005 2005-12-08
  • 打赏
  • 举报
回复
//结论: 创建一个对象指针,就可以调用其 静态成员函数 和 不涉及普通成员变量的函数(不涉及普通成员变量那就也相当于静态成员函数了)。
//创建对象时,仅分配用于保存普通数据成员的空间,而函数代码和静态数据成员则由各个对象共享。
//只有对象指针==》虽然没分配保存普通数据成员的空间,其共享部分都已经存在并可以访问、使用。但一涉及到普通数据成员就出错。因为对象不存在!

//是不是创建一个对象申请一份数据空间。共享部分就使用类定义体那里,创建一个类的时候已经申请了空间存在了????????
cky41 2005-12-08
  • 打赏
  • 举报
回复
这不是bug,而且讲得通
Johnny_de 2005-12-08
  • 打赏
  • 举报
回复
我感觉这是个BUG.和this没什么关系.逻辑上是讲不通的。
cky41 2005-12-08
  • 打赏
  • 举报
回复
C++的对象在内存中其实和C的struct没什么区别,都是一陀数据的空间,C++类中的函数并没有放在对象所在的空间中,也不是一个对象会有一份函数代码,而是所有对象共享一份函数代码(好像静态函数哈)
所以编译器只要看出是这个类的指针“A* pa”,那么用“pa->func();”时,编译器就会到那个存放函数代码的公共部分去找这个函数,自然会找到,而你这个函数中有没有访问类的成员变量,那么就不会去找对象所在的内存,也就不会出错了。

其实也就是说像这样的函数是这个类所有对象共有的(甚至无效对象),也就是说它实质就是一个类的静态函数或者干脆全局函数
wohow 2005-12-08
  • 打赏
  • 举报
回复
以上是普通成员函数,静态成员函数没有this指针
加载更多回复(3)

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧