C++的静态绑定

    今天在 ”高性能服务器开发“ 群里看到一个问题,觉得挺有意思的就记录了下来。

    首先讨论的代码如下:

class A
{
public:
  void prin(void)
  {
    cout << "for testing" << endl;
  }
};

int main(void)
{
  A *a = NULL;
  a->prin();

  return 0;
}

    相信很多人看到这样的代码,觉得程序会报 “segment fault”, 但是结果却是输出“for testing”,程序正常运行。

    解析是:

A *a = NULL;
a->prin();    // 当调用这个成员函数的时候,只是把NULL空指针传递给了 prin()函数的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;
}

程序运行时,会报“segment fault” 错误。

解析参照别人的,如下

因为对于非虚成员函数,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++的行为。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值