C++类对象空指针访问成员函数(静态绑定)
2016-08-06 16:08
267 查看
题目:
class A{ public: void test(){printf("test A");} }; int main(){ A*pA=NULL; pA->test(); }
结果是输出“test A”而不是程序崩溃,原因如下:
一种解释:
A*pA=null;
pA->test();//当调用成员函数时,只是将实参
null传给
this指针
test成员函数中并无任何需要通过this指针访问的数据成员,因此没有带来任何影响
会崩溃的情况,调用的成员函数需要通过this指针访问类的数据成语
#include<stdio.h> class A{ public: void test1(){ printf("test 1"); } void test2(){ printf("test 2%d",data); } private: int data = 10; }; int main(){ A*pA = NULL; pA->test1();//成功输出”test 1" pA->test2();//程序崩溃(注意不是编译错误) return 0; }
结果:运行时崩溃
-
0x00E013E8 处有未经处理的异常(在 code_test.exe 中): 0xC0000005: 读取位置 0x00000000 时发生访问冲突。
跟详细的解释:从c++静态绑定谈起
因为对于非虚成员函数,C++这门语言是静态绑定的。这也是C++语言和其它语言Java, Python的一个显著区别。以此下面的语句为例:pA->test();
这语句的意图是:调用对象 pA 的 test 成员函数。如果这句话在Java或Python等动态绑定的语言之中,编译器生成的代码大概是:
找到 pA 的 test 成员函数,调用它。(注意,这里的找到是程序运行的时候才找的,这也是所谓动态绑定的含义:运行时才绑定这个函数名与其对应的实际代码。有些地方也称这种机制为迟绑定,晚绑定。)
但是对于C++。为了保证程序的运行时效率,C++的设计者认为凡是编译时能确定的事情,就不要拖到运行时再查找了。所以C++的编译器看到这句话会这么干:
1. 查找 pA 的类型,发现它有一个非虚的成员函数叫 test 。(编译器干的)
2. 找到了,在这里生成一个函数调用,直接调A:: test ( pA )。
所以到了运行时,由于 test ()函数里面并没有任何需要解引用 pA 指针的代码,所以真实情况下也不会引发segment fault。这里对成员函数的解析,和查找其对应的代码的工作都是在编译阶段完成而非运行时完成的,这就是所谓的静态绑定,也叫早绑定。
正确理解C++的静态绑定可以理解一些特殊情况下C++的行为。
相关文章推荐
- 非常对象访问常成员函数,导致内部this指针无法访问非常成员函数
- C++类的对象和类的指针的区别
- 神奇的虚函数:用基类指针访问对象的protected成员函数
- 项目二.1(指针访问对象)
- 常对象只能由常指针访问
- 用指针访问对象
- 通过操作地址的方法来访问C++类对象中私有成员变量
- 【转】对C++类的对象和类的指针的理解
- 第六周项目二:指针访问对象(a)
- 用指针访问对象
- 用对象和用指向基类的指针访问成员函数
- 关于访问C++类对象中私有成员变量的方法,不考虑用友元
- 两层指针共用一个智能指针控制基本对象的操作--成员访问操作符
- C++类对象创建过程(分配空间、赋值和初始化、对象初始化顺序、虚函数表指针)
- 用指针访问对象
- c++类对象和指针的区别
- C++学习总结_指针访问堆内存中创建的对象
- 第六周 RW(2.1)用指针访问对象
- 访问C++类对象中私有成员变量的方法
- 6-2-a 用指针访问对象