A* p=NULL; p->Display()...如此诡异的代码。。----class object如何调用class memmber functions

 

A* p=NULL; p->Display()...如此诡异的代码。。
请看下面的程序
class foo
{
public:
foo() { m_nVar1 = 100;};
~foo(){};
void Display()
{
printf( " m_nVar2 is %d", m_nVar2 );
}
int m_nVar1;
static int m_nVar2;

};

int foo::m_nVar2 = 500;

int main(int argc, char* argv[])
{

foo *p = NULL;
p->Display();

_getch();
return 0;
}

请问哪种说法是正确的:
A. 程序编译错误。
B. 程序编译正确,但是运行时发生异常
C. 程序编译正确,运行时有时正常,有时发生异常。
D. 程序编译正确,运行时正常

你的选择是哪一个?


正确答案:D

虽然这样的代码在实际的编程中是不允许或者不推荐出现的。
但是,了解一下背后的原理,还是很有用的 :)
解释:
p->Display();

使得Display()方法中的this参量指向p,这里由于p指向空,所以,this也指空。
但是display()中并没有访问对象p的成员属性,只是访问了类属性——static int m_nVar2
它不在*p所处的存储空间中,而是在全局静态区域。所以这里没有访问空地址的内容,故程序运行时正常。
而如果在Display()方法中访问了m_nVar1,编译连接全通过,发生运行时异常(存储空间受保护情况下)。

事实上,虽然没有对象存在,但编译时,p->Display()仍正确指向了Display()函数的地址。
为什么 p没有指向任何对象 p->Display()却仍正确指向了Display()函数的地址。
事实上,编译器在编译一个类的时候,都把类内部的成员函数作为全局函数实现的。。。毕竟,世界上本没有类。。那是人们抽象出来的,底层一个类的时候,,就要回到C时代了。
具体解释见:
BEGIN
class object如何调用class memmber functions
------------------------------------------------------------------------------
类的成员函数在编译时会被“name mangling(名称重整)”,下面具个例子给楼主说明一下如何通过类对象调用member function(仅仅是个例子,编译器的做法可能大同小异)。

class foo{
public:
    int i;
    void test(int a){
         i = a;
    }
};
foo f;
f.test(5);//调用成员函数

上面程序经过编译器整理后可能变成下面样子:
struct foo{
public:
    int i;
};
void test_foo(foo *const this, int a){//原来的成员函数现在变成了一个全局函数(或者说是“名字空间域函数”),而且名字被“重整”了,以反映出原来是“class foo”的成员(再次强调一下,不同编译器有不同的重整方法)。而且,增加了一个新的参数"this",见下面的调用方式,就明白他的用途了
    this->i =a;//通过this指针访问对象的数据成员
}

foo f;
test_foo(&f, 5);//将对象f的地址作为this指针传递给test_foo函数,以便访问数据成员
END

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值