最近在看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. [置顶] perl脚本中defined,exists和delete关键字的用法和区别

    刚学习perl脚本的时候,喜欢频繁使用defined关键字判断一个hash中某个key是否存在,后来程序出了问题才去perl官方文档查看关于defined关键字的准确使用方法.因此,这里我把perl中 ...

  2. hql中不能写count(1)能够写count(a.id)

    hql中不能写count(1)能够写count(a.id)里面写详细的属性 String hql="select new com.haiyisoft.vo.entity.cc.repo.Bu ...

  3. FZU Problem 2169 shadow

    http://acm.fzu.edu.cn/problem.php?pid=2169 题目大意: S王国有N个城市,有N-1条道路.王都为编号1的城市.叛军驻扎在很多城市.除了王都外有K个城市有军队, ...

  4. c 按输入的字母来输出对应效果

    输入一个大写字母,如 F,输出 比如: 输入:F 输出: F EFE DEFED CDEFEDC BCDEFEDCB ABCDEFEDCBA #include<stdio.h> int m ...

  5. Spring源码地址和相关介绍的网址

    Spring源码地址下载: https://github.com/spring-projects/spring-framework/tags >多图详解Spring框架的设计理念与设计模式:ht ...

  6. Codeforces Round #316 (Div. 2C) 570C Replacement

    题目:Click here 题意:看一下题目下面的Note就会明白的. 分析:一开始想的麻烦了,用了树状数组(第一次用)优化,可惜没用. 直接判断: #include <bits/stdc++. ...

  7. Laravel 简单使用七牛云服务

    前言 路漫漫其修远兮,吾将上下而求索.学习 Laravel 之初觉得所有东西都很厉害的样子,现在看来就是很厉害啊!最近在写一个项目上传的模块,要上传图片到七牛云,昨天看了一下午七牛云官方的文档感觉还是 ...

  8. 在Outlook中设置QQ邮箱

    原本以为在Outlook中设置QQ邮箱没多大难度,但我错了,估计错了腾讯的麻烦程度,故记录下来. ----- 打开Outlook 2013(Outlook 2010也差不多),若是第一次打开会提示你设 ...

  9. Python学习之一

    运行Python的步骤 1 加载内存 2 词法分析  3 语法分析 4编译字节码=>机器码  5运行   11:03:49 2016-01-11

  10. linux系统调用和库函数调用的区别(转)

    Linux下对文件操作有两种方式:系统调用(system call)和库函数调用(Library functions).可以参考<Linux程序设计>(英文原版为<Beginning ...