最近在看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