c++空指针调用类成员函数
最近在看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++空指针调用类成员函数的更多相关文章
- 理解ATL中的一些汇编代码(通过Thunk技术来调用类成员函数)
我们知道ATL(活动模板库)是一套很小巧高效的COM开发库,它本身的核心文件其实没几个,COM相关的(主要是atlbase.h, atlcom.h),另外还有一个窗口相关的(atlwin.h), 所以 ...
- 直接调用类成员函数地址(用汇编取类成员函数的地址,各VS版本还有所不同)
在C++中,成员函数的指针是个比较特殊的东西.对普通的函数指针来说,可以视为一个地址,在需要的时候可以任意转换并直接调用.但对成员函数来说,常规类型转换是通不过编译的,调用的时候也必须采用特殊的语法. ...
- boost::function 通过boost::bind调用类成员函数
1. 首先引用boost::function和boost::bind的头文件和库: #include "boost/bind.hpp" #include "boost/f ...
- 116-PHP调用类成员函数
<?php class ren{ //定义人类 public function walk(){ //定义人类的成员方法 echo '我会走路.'; } } $ren=new ren(); //实 ...
- [转]浅谈C++指针直接调用类成员函数
找了一番之后发现这篇文章讲的很清楚. 传送门
- 深入理解类成员函数的调用规则(理解成员函数的内存为什么不会反映在sizeof运算符上、类的静态绑定与动态绑定、虚函数表)
本文转载自:http://blog.51cto.com/9291927/2148695 总结: 一.成员函数的内存为什么不会反映在sizeof运算符上? 成员函数可以被看作是类 ...
- 如何线程调用C++类成员函数
方法就是: 1,写成静态成员函数 2,参数为 (void* __this)用来传入类 对象指针(this) 3,进入函数首先 C类名 *_this = (C类名*)__this; 转化为对象指 ...
- C++ 11 智能指针(shared_ptr)类成员函数详解
C++ 11 模板库的 <memory> 头文件中定义的智能指针,即 shared_ptr 模板类,用来管理指针的存储,提供有限的内存回收函数,可同时与其他对象共享该管理功能. share ...
- C++学习46 getline()函数读入一行字符 一些与输入有关的istream类成员函数
getline函数的作用是从输入流中读取一行字符,其用法与带3个参数的get函数类似.即 cin.getline(字符数组(或字符指针), 字符个数n, 终止标志字符) [例13.7] 用get ...
随机推荐
- hdu1281结题报告
哎哎...自己刚刚一看到这个题目居然.....什么都想不到...看了一下别人的解题报告说最大匹配...于是就自己开始构思啦... 对于这个棋盘,有K个可以放棋子的位置....那么 首先我们开始可以求出 ...
- 【Spring】手动获取spring容器对象时,报no qualifying bean of type is defined
手动获取容器对象时,报no qualifying bean of type is defined, 经过调查,发现手动获取的时候,该类所在的包必须经过spring容器初始化. 1.SpringConf ...
- C# Best Practices - Define Fields Appropriately
Backing Fields private string description; private int productId; Features A variable in a class Hol ...
- java volatile关键字的理解
转载:http://shmilyaw-hotmail-com.iteye.com/blog/1672779 一个多线程的示例引发的问题 在讨论这个关键字之前先看一个多线程的示例代码: public c ...
- C++之对象组合
#include<stdio.h>//初始化列表 提供了对成员变量初始化的方式//Constructor class M { private: ...
- [Linux命令]查看Linux系统相关命令
#查看系统内核/操作系统/CPU信息 uname -a #返回:内核名 主机名 Linux内核版本 内核编译日期 操作系统版本 CPU型号 硬件平台 GNU/Linux#查看系统是32位还是64位un ...
- Oracle 创建用户并且授权
以sysdba登陆 创建用户:CREATE USER username IDENTIFIED BY password; 授予(角色)权限:GRANT CONNECT,RESOURCE TO usern ...
- C#中foreach语句的迭代器实现机制
C#中的foreach语句可用于循环遍历某个集合中的元素,而所有的只要支持了IEnumerable或IEnumerable<T>泛型接口的类型都是可以 用foreach遍历的.其具体的遍历 ...
- OpenGL ES 正反面设置指令
在OpenGL ES 中,仅有一种表面网格表示方式,那就是三角形. 三角形的三个顶点,可以组几个面?有答 1 的没有?有!那就是还不懂OpenGL ES 的我. 事实上,一张纸是有正反面的,那么一个三 ...
- eclipse没有New Java Class的解决办法
配置之前的截图: 配置步骤: