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 ...
随机推荐
- Android应用--简、美音乐播放器增加音量控制
Android应用--简.美音乐播放器增加音量控制 2013年6月26日简.美音乐播放器继续完善中.. 题外话:上一篇博客是在6月11号发的,那篇博客似乎有点问题,可能是因为代码结构有点乱的原因,很难 ...
- C++使用之常量的定义
在介绍C++的常前,先看下下面的代码. for (int i = 0; i < 512; ++i) { …; } 512是什么,它具有什么含义?在代码中若直接使用类似512这些“魔数”(magi ...
- GridView事件分析
GridView事件分析 (转) P1默认数据绑定过程 编号 事件名称 作用 E1 DataBinding 数据绑定之前触发,在这个事件之前(第一次生成GridView),GridView不存在行数据 ...
- js如何判断一个对象是不是Array?(转载)
js如何判断一个对象是不是Array? 在开发中,我们经常需要判断某个对象是否为数组类型,在Js中检测对象类型的常见方法都有哪些呢? typeof 操作符 对于Function, String, Nu ...
- java注解入门(含源码下载)
注解(Annotation)是从jdk1.5开始增加的特性.学习注解能够读懂框架的代码:让编程更加简洁,代码更加清晰. 注解概念:java提供了一种原程序中的元素关联任何信息和任何元数据的途径和方法. ...
- resolve "Undefined attribute name" warning for Angular "ng-" attributes in HTML files
由于这些attributes引起的warning数量较多, 影响直观查找其他warning. 因此选择将这类warning忽视掉: Project Property -> Validation ...
- [LeetCode]题解(python):029-Divide Two Integers
题目来源: https://leetcode.com/problems/divide-two-integers/ 题意分析: 不用乘法,除法和mod运算来实现一个除法.如果数值超过了int类型那么返回 ...
- apache下的IfModule里设置含义
<IfModule mod_deflate.c> SetOutputFilter DEFLATE #必须的,就像一个开关一样,告诉apache对传输到浏览器的内容进行压缩 SetEnvIf ...
- NSString 用法大全。
一.NSString 创建字符串. NSString *astring = @"This is a String!"; 创建空字符串,给予赋值. NSString *astri ...
- linux禁ping和允许ping的方法
一.系统禁止ping [root@linuxzgf ~]# echo 1 >/proc/sys/net/ipv4/icmp_echo_ignore_all 二.系统允许ping [root@li ...