C++ 空指针调用函数 静态绑定

本文通过一个具体的C++代码示例解释了静态绑定的概念,并对比了动态绑定的区别。阐述了C++如何在编译阶段确定函数调用的目标,即使是指针为空也能正确执行的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先看一段代码是否知道其正确还是错误。
class A{
public:
void print()
{
cout << "Hello" << endl;
}


};
void main()
{
A *a = NULL;
a.print();
}
问你程序是否正确执行,或者执行结果是什么。
这就是一个典型的表示C++是一个静态语言的特征。可以阐明“静态绑定”和“动态绑定”的区别。真正的原因是:因为对于非虚成员函数,C++这门语言是静态绑定的。这也是C++语言和其它语言Java, Python的一个显著区别。C++奉行的原则是能够在编译时候搞定的事情绝不拖到运行时搞定。我们的第一感觉是这个程序应该是错的,然而事实却是相反的。每个对象都有指向自己的this指针,指针的值会因为不同的对象不同而不同,用来区别不同的对象。这里的this指针就是一个NULL。如果我们调用this指针的时候就会出错。可是这个函数并没有用到this指针就是简单的输出字符串,这一过程在编译阶段就已经完成了。所以不会报错。
但是对于C++。为了保证程序的运行时效率,C++的设计者认为凡是编译时能确定的事情,就不要拖到运行时再查找了。所以C++的编译器看到这句话会这么干:
1:查找a的类型,发现它有一个非虚的成员函数叫print。(编译器干的)
2:找到了,在这里生成一个函数调用,直接调A::print()。
所以到了运行时,由于print函数里面并没有任何需要解引用somenull指针的代码,所以真实情况下也不会引发segment fault。这里对成员函数的解析,和查找其对应的代码的工作都是在编译阶段完成而非运行时完成的,这就是所谓的静态绑定,也叫早绑定。
正确理解C++的静态绑定可以理解一些特殊情况下C++的行为。
C++中,通过指针调用函数的方式通常有两种情况:普通函数指针和成员函数指针。以下是详细的说明及示例: --- ### **一、普通函数的指针调用** 对于非相关的全局函数静态函数,可以定义一个函数指针来指向目标函数,并通过这个指针间接调用。 #### 步骤: 1. 定义一个函数指针,型需匹配目标函数。 2. 将目标函数的地址赋值给该指针。 3. 使用指针调用函数。 #### 示例代码: ```cpp #include <iostream> using namespace std; // 函数原型 void greet() { cout << "Hello from function!" << endl; } int main() { // 1. 声明函数指针并将其绑定到greet函数 void (*funcPtr)() = &greet; // 2. 调用函数 (可通过解引用或直接使用) funcPtr(); // 等价于 (*funcPtr)(); return 0; } ``` **注意点**: 如果函数有参数,则函数指针也需要带上相同的参数列表。 例如: ```cpp double add(double a, double b); double (*mathFunc)(double, double) = add; cout << mathFunc(5.0, 3.0); // 输出8.0 ``` --- ### **二、成员函数的指针调用** 由于成员函数依赖于所属的对象实例(this指针),所以其调用方式稍复杂一些。 #### 格式化表达: 假设有一个 `MyClass` 包含成员函数 `myMethod()`,我们可以通过如下的步骤完成调用: 1. 定义成员函数指针型为 `(MyClass::*memberFunctionPointer)()`; 2. 把具体的成员函数地址赋予上述型的指针变量; 3. 结合实际对象一起触发调用动作。 #### 示例代码: ```cpp #include <iostream> using namespace std; class MyClass { public: void sayHello() { cout << "Hello from member function!" << endl; } }; int main(){ MyClass obj; // 实例化对象 // 成员函数指针定义 + 初始化 void (MyClass::*ptrToMemberFn)() = &MyClass::sayHello; // 对象结合成员函数指针调用 (obj.*ptrToMemberFn)(); // 调用成员函数 return 0; } ``` **注意事项**: - 需要用特殊的语法结构`(object.*pointer_to_member_function)` 或者 `(pointerToObject->*pointer_to_member_function)`来进行调用。 - 成员函数指针比普通函数指针更难理解因为额外涉及到了“绑定”的概念即每个这样的呼叫都需要关联至某个特别的物件个体之上才能够正常运作起来。 --- ### 总结 无论是普通的自由函数还是嵌套于某一别当中的方法都可以借助相应的功能型别指示器达成灵活运用的目的;这种技巧尤其适用于诸如回调机制等场景之中显得尤为重要不可替代!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值