最近在看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. js 获取前天、昨天、今天、明天、后天的时间

    js 获取前天.昨天.今天.明天.后天的时间 2011-05-19 21:03   <html><head><meta http-equiv="Content- ...

  2. 带你走进EJB--MDB

    在之前的文章中我们介绍了带你走进EJB--JMS 和 带你走进EJB--JMS编程模型 对JMS有了初步的了解, 作为EJB系列的文章我们会继续对EJB相关的内容做进一步深的学习和了解.而此次需要进行 ...

  3. Thrift对多接口服务的支持

    Thrift对多接口服务的支持 Thrift在0.9.1版本之前,一直只提交了对单一接口服务的支持,即一个RPC服务器(对应一个端口)支持一个服务接口的实现. 但是很多时候,我们的服务不能实现在一个接 ...

  4. ajax 基础

    <html><head><script type="text/javascript">function showHint(str){var xm ...

  5. 请求接口获取到的数据其中出现null值,处理的时候导致了程序crash,解决方案如下:

    第一种方法是使用分类给字典添加一个类方法,将字典中的null值全部替换为空字符串,代码如下: .h文件代码: @interface NSDictionary (DeleteNull) + (id)ch ...

  6. centos 5.8 x64Jetty的安装以及项目部署配置

    链接地址:http://blog.csdn.net/shuixin536/article/details/9049821 安装环境 centos 5.8 x64 安装前须知 首先在安装Jetty之前要 ...

  7. JavaSE学习总结第01天_Java概述

      01.01 计算机概述 计算机(Computer):全称电子计算机,俗称电脑. 是一种能够按照程序运行,自动.高速处理海量数据的现代化智能电子设备. 由硬件和软件所组成,没有安装任何软件的计算机称 ...

  8. 1724: [Usaco2006 Nov]Fence Repair 切割木板( 贪心 )

    倒过来看 , 每次总是选择最短的两块木板合并 , 用heap维护 ------------------------------------------------------------------- ...

  9. thinkphp中Conf的配置

    -----www ----------admin -------------Conf ----------admin.php ----------Home -------------Conf ---- ...

  10. 如何正确的在java web配置数据池

    在tomcat context.xml中配置数据 <Context reloadable="true"> <!-- Default set of monitore ...