最近在看C++动态绑定问题时(理解静态绑定时)发现的问题:能用空指针调用类的成员函数(gcc,vs2013下都可以)。

例子:

class animal  {
public:
void sleep(){ cout << "animal sleep" << endl; }
void breathe(){ cout << "animal breathe haha" << endl; }
};
class fish :public animal{
public:
void breathe(){ cout << "fish bubble" << endl; }
};
int _tmain(int argc, _TCHAR* argv[]){
animal *pAn=nullptr;
pAn->breathe(); // 输出: animal breathe haha
fish *pFish = nullptr;
pFish->breathe(); // 输出: fish bubble
return 0;
}

C++类的内存布局

  • 类的成员函数与成员对象内存中不放一起。
  • 对于类成员函数而言,此类的所有对象共用这个成员函数体,并不是一个对象对应一个单独的成员函数体。
  • 在类初始化的时候,编译器会将它的函数分配到类的外部,当然这也包括静态成员函数
  • 当程序被编译之后,此成员函数地址即已确定。

这样的做法,主要是为了节约内存,这也是为什么静态函数可以在对象初始化之前运行的原因。

C++类的this指针

  • 类的每个对象,都有一个指向自己的this指针,但不占用类对象空间(?)。
  • 这个指针的值,将会因为对象的不同而不同;
  • 它的作用主要就是用来区分不同的对象,同一个成员函数把类的各个对象的数据区别开。

    这样你就可以根据this来访问不同的对象的成员变量。

编译器编译后的成员函数的第一个参数是this指针(最后一个参数?),通过this指针引用数据成员及调用其它成员函数。

函数体内所有对类数据成员的访问, 都会被转化为this->数据成员的方式。

c++空指针调用类成员函数

为什么,因为在编译时对象就绑定了函数地址,和指针空不空没关系;

pAn->breathe();编译的时候,函数的地址就和指针pAn绑定了;

调用breath(*this),this就等于pAn。

由于函数中没有需要解引用this的地方,所以函数运行不会出错,但是若用到this,因为this=nullptr,运行出错。

这里对成员函数的解析,和查找其对应的代码的工作都是在编译阶段完成而非运行时完成的,这就是所谓的静态绑定,也叫早绑定。

这是一个c++静态绑定的很好的例子,正确理解C++的静态绑定可以理解一些C++特殊情况下的行为。

reference:

http://www.zhihu.com/question/23260677

http://www.unjeep.com/q/895161.htm

http://segmentfault.com/q/1010000000611307

http://blog.csdn.net/huangzeyy/article/details/7186792

c++空指针调用类成员函数的更多相关文章

  1. 理解ATL中的一些汇编代码(通过Thunk技术来调用类成员函数)

    我们知道ATL(活动模板库)是一套很小巧高效的COM开发库,它本身的核心文件其实没几个,COM相关的(主要是atlbase.h, atlcom.h),另外还有一个窗口相关的(atlwin.h), 所以 ...

  2. 直接调用类成员函数地址(用汇编取类成员函数的地址,各VS版本还有所不同)

    在C++中,成员函数的指针是个比较特殊的东西.对普通的函数指针来说,可以视为一个地址,在需要的时候可以任意转换并直接调用.但对成员函数来说,常规类型转换是通不过编译的,调用的时候也必须采用特殊的语法. ...

  3. boost::function 通过boost::bind调用类成员函数

    1. 首先引用boost::function和boost::bind的头文件和库: #include "boost/bind.hpp" #include "boost/f ...

  4. 116-PHP调用类成员函数

    <?php class ren{ //定义人类 public function walk(){ //定义人类的成员方法 echo '我会走路.'; } } $ren=new ren(); //实 ...

  5. [转]浅谈C++指针直接调用类成员函数

    找了一番之后发现这篇文章讲的很清楚. 传送门

  6. 深入理解类成员函数的调用规则(理解成员函数的内存为什么不会反映在sizeof运算符上、类的静态绑定与动态绑定、虚函数表)

    本文转载自:http://blog.51cto.com/9291927/2148695 总结: 一.成员函数的内存为什么不会反映在sizeof运算符上?             成员函数可以被看作是类 ...

  7. 如何线程调用C++类成员函数

    方法就是: 1,写成静态成员函数 2,参数为 (void* __this)用来传入类 对象指针(this) 3,进入函数首先    C类名 *_this = (C类名*)__this;  转化为对象指 ...

  8. C++ 11 智能指针(shared_ptr)类成员函数详解

    C++ 11 模板库的 <memory> 头文件中定义的智能指针,即 shared_ptr 模板类,用来管理指针的存储,提供有限的内存回收函数,可同时与其他对象共享该管理功能. share ...

  9. C++学习46 getline()函数读入一行字符 一些与输入有关的istream类成员函数

    getline函数的作用是从输入流中读取一行字符,其用法与带3个参数的get函数类似.即    cin.getline(字符数组(或字符指针), 字符个数n, 终止标志字符) [例13.7] 用get ...

随机推荐

  1. HDU 4569 Special equations (数学题)

    题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4569 题意:给你一个最高幂为4的一元多项式,让你求出一个x使其结果模p*p为0. 题解:f(x)%(p ...

  2. Unity5.0 RPG角色扮演历险类游戏之 森林历险记

    http://v.youku.com/v_show/id_XMTI1MjEyNjc4MA==.html? from=y1.7-1.2

  3. C++设计模式实现--组合(Composite)模式

    一. 举例 这个样例是书上的,如果有一个公司的组结结构例如以下: 它的结构非常像一棵树,当中人力资源部和財务部是没有子结点的,详细公司才有子结点. 并且最关健的是,它的每一层结构非常相似. 代码实现例 ...

  4. PHP程序猿必须学习的第二课——站点安全问题预防

    作为PHP程序猿.第一课我们学习了基本的语法.那么在熟悉基本的语法之后我们应该学些什么呢?我觉得是安全问题.安全问题基于一个站点宛如基石,一着不慎,意味着灾难性的事故. 这里主要就提三点最简单,也是最 ...

  5. 上传列表集合wsp包

    1. 网站设置--web设计器库--解决方案--上载解决方案 2. 打开SPD,左侧的子网站--新建

  6. 把Orchard部署到Windows Azure Web Sites

    很久前就想做个人站点,主要用来记录自己的生活,我喜欢摄影,烘焙…然后又刚刚入皮坑,这些都可以放在网站上展示一下,或许还能为自己带来收入. 然后手上刚好有Azure的试用,于是乎动力就上来了. 以下是部 ...

  7. HtmlUnit+Jsoup 解决爬虫无法解析执行javascript的问题

    本人最近在研究爬虫.作为一个新手.研究了些爬虫框架,发现所有开源的爬虫框架很多,功能也很齐全,但唯独遗憾的是,目前还没有发现那个爬虫对js完美的解释并执行.看了浅谈网络爬虫爬js动态加载网页(二)之后 ...

  8. 2013 南京邀请赛 A play the dice 求概率

    /** 大意:给定一个色子,有n个面,每一个面上有一个数字,在其中的m个面上有特殊的颜色,当掷出的色子出现这m个颜色之一时,可以再掷一次..求其最后的期望 思路:假设 期望为ans 4 ans = 1 ...

  9. OC中的类型强制转换

    在Objective-C中,以数字格式组成的字符串经常需要转换为NSNumber对象后再使用.例如有一个字符串对象@"111.22",需要转为NSNumber对象,最简单的方法就是 ...

  10. slf4j 和 log4j合用的(Maven)配置(转)

    简述:添加logger的日志输出,下面是配置信息供备忘 步骤:1. 在Maven的porn.xml 文件中添加dependency如下 <dependency> <groupId&g ...