类成员函数本质论

请提出以下程序运行的结果.并说明为什么
#include<iostream>
using namespace std;
class A
{
public:
void dis(){cout<<"AAA"<<endl;}
};
int main()
{
A *p;
{
A a;
p=&a;
}
p->dis();
return 1;
}
===================

1。这个显示什么不能定的
a对象已经出了生存期,在}的地方析构,后面p指向一个无效内存区域
调用dis显示随机内容
从析构函数角度来说,析构函数已经执行,它通知系统并不再为这块内存维护类对象的一个数据结构了,此时如果其他线程访问这块内存,系统可以分配给其他线程使用,这个程序能够
正常的执行因为单线程,无其他线程可能马上破坏析构后的对象所占据的内存空间

2。类的成员函数在编译时会被“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函数,以便访问数据成员

p->Display();

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

在编译器的内部:类函数的存储空间分配与类无关 :
f;;Display()被转化成了Display(foo* this) 的形式:
foo *p = NULL;
p->Display();
相当于:
foo *p=NULL;
Display(p);
p赋NULL 对访问静态成员不影响

在大多数编译器上,应该都是没问题的。
原因在于Display虽然不是静态函数,但幸运的是,其函数体中也没有任何访问非静态成员的语句,也就是说,对于这个Display来说,它根本没有用到自己的那个默认参数“this”,因此,虽然this当前为NULL,但所幸没有大碍。
还有一点需要注意的是,这个Display幸好也不是virtual的,否则运行时可能需要顺着this去找vtable,也可能发生问题(编译器若优化成静态绑定就另当别论了)。

从上面的分析也可看出,虽然这个代码似乎没什么问题,但它毕竟比较脆弱,所以还是不要这样为好,写出这样的代码主要有两点危险:
(1)在实际的项目开发中,代码总是被不断维护着的,而并非一次写好后就绝不再变。因此很可能以后有一个维护程序的人(可能是你自己,也可能不是)在这个Display中加入了别人语句,导致this指针实际被用到。
(2)实际上,C++语言标准中并没有规定必需采用什么机制来实现对象模型,也就是说,即使现在你试过的所有编译器都没问题,也不代码在将来一种新的编译器上同样没问题。比如说,一种编译器,完全可以在其DEBUG版中加入一些增强型的调试功能,要求任何一个非静态函数在被调用之前,必段满足“this指针不空”这个前条件——我不觉得这有什么不合理。

3。1+2的解释合理,静态成员函数,普通未访问数据成员的成员函数,this指针为无效的时候也可执行(仅仅能执行),访问数据成员的时候,由于对象已经析构,通知系统不维护这块内存为类对象,所以数据成员的值所在的内存可以让其他的线程所修改,所以会不执行。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值