为什么NULL指针也能访问成员函数?(但不能访问成员变量)
查看更加详细的解析请参考这篇文章:http://blog.51cto.com/9291927/2148695
看一个静态绑定的例子:
1 #include <iostream>
2
3 using namespace std;
4
5 class A
6 {
7 public:
8 int a = 3;
9 void test1()
10 {
11 printf("test A\n");
12 }
13 void test2()
14 {
15 cout << a;
16 }
17 };
18
19 int main()
20 {
21 A *pA = NULL;
22 cout << pA.a; //错误:NULL指针不能访问类非static的成员变量
23 pA -> test1(); //正确:输出test A
24 pA -> test2(); //错误:NULL指针不能访问类非static的成员变量
25 return 0;
26 }
分析: 由于test是非虚函数,对于非虚成员函数,C++是静态绑定的,即在编译时就确定了,即编译器在编译的时候就知道。空对象指针不能访问非static成员变量,但可以访问成员函数( 非虚函数 ),因为数据成员要分配内存才能访问,而函数是不需要的。
解析(1):
这语句的意图是:调用对象 pA 的 test 成员函数。如果这句话在Java或Python等动态绑定的语言之中,编译器生成的代码大概是:
找到 pA 的 test 成员函数,调用它。(注意,这里的找到是程序运行的时候才找的,这也是所谓动态绑定的含义:运行时才绑定这个函数名与其对应的实际代码。有些地方也称这种机制为迟绑定,晚绑定。)
但是对于C++。为了保证程序的运行时效率,C++的设计者认为凡是编译时能确定的事情,就不要拖到运行时再查找了。所以C++的编译器看到这句话会这么干:
1:查找 pA 的类型,发现它有一个非虚的成员函数叫 test 。(编译器干的)
2:找到了,在这里生成一个函数调用,直接调A:: test ( pA )。
所以到了运行时,由于 test ()函数里面并没有任何需要解引用 pA 指针的代码,所以真实情况下也不会引发segment fault。这里对成员函数的解析,和查找其对应的代码的工作都是在编译阶段完成而非运行时完成的,这就是所谓的静态绑定,也叫早绑定。
正确理解C++的静态绑定可以理解一些特殊情况下C++的行为。
解析(2):
test函数作为非虚函数,在编译时就确定了。即使pA为null,但是已经声明了类型,就知道pA有个test函数,且test函数里没有用到成员变量,单单一个打印语句是可以运行成功的。
本题中NULL指针调用成员函数的时候成员函数中没有成员变量,如果访问此对象的成员函数,则程序崩溃,因为this指针是NULL
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南