关于一个类的空指针可以调用成员函数的问题:静态绑定

首先看一下代码:

//============================================================================
// Name        : Adapter.cpp
// Author      : 
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
using namespace std;

class Target {
public:
     virtual void Request() {
        cout << "Target::Request..." << endl;
    }
    virtual ~Target() { }
};

class Adaptee {
public:
    void SpecificRequest() {
        cout << "Adaptee::SpecificRequest..." << endl;
    }
};

class Adapter :public Target, private Adaptee {
public:
	Adapter():_ade(NULL) {
		if(!_ade)
			cout << "_ade is NULL" << endl;
	}
    Adapter(Adaptee* ade) {
        _ade = ade;
    }
    void Request() {
        _ade->SpecificRequest();
    }
private:
    Adaptee *_ade;
};

int main() {
    Adaptee *adaptee = new Adaptee();
    Target *adapter1 = new Adapter(adaptee);

    adapter1->Request();//adapter实际指向Adapter  _ade不为空

    Target *adapter2 = new Adapter();//_ade为空
    adapter2->Request();

    delete adapter1;
    delete adaptee;
    delete adapter2;

    return 0;
}

运行结果:


惊不惊喜。。。。。

这里就涉及到c++面向对象的编程种涉及到的静态绑定和动态绑定的知识了。

1.对象的静态类型:对象在声明时采用的类型(编译器确定)

2.对象的动态类型:当前所指的对象类型,动态类型是动态绑定的,可以改变。

例如: 

Adaptee *adaptee = new Adaptee();  //静态类型和动态类型都是Adaptee*
Target *adapter1 = adaptee; //静态类型是adapter1, 动态类型是指针指向的Adaptee*

3.静态绑定:绑定的是对象的静态类型,某特性(比如函数)依赖于对象的静态类型,发生在编译期。(为了保证程序运行时的效率,凡是能在编译期做的事情就不会在运行期干)

例如: _ade->SpecificRequest()在编译期会生成这样的代码:Adaptee::SpecificRequest(_ade)

4.动态绑定:绑定的是对象的动态类型,某特性(比如函数)依赖于对象的动态类型,发生在运行期。

例如:  B继承A 存在一个虚函数testvirtual()和一个非虚函数test(), B* b = new B(); A* a = b; a->testvirtual()和b->testvirtual()都会绑定的是B:testVirtual();  但 a->test()绑定的是A::test(a), b->test()绑定的是B::test(b).

总结一句: 非虚函数和类型绑定,和对象无关;非静态成员和对象绑定,和类型无关。

需要注意的是:

1.当缺省参数和虚函数一起出现的时候情况有点复杂,极易出错。我们知道,虚函数是动态绑定的,但是为了执行效率,缺省参数是静态绑定的。(绝不重新定义继承而来的缺省参数

2.绝对不要重新定义继承而来的非虚(non-virtual)函数(《Effective C++ 第三版》条款36),因为这样导致函数调用由对象声明时的静态类型确定了,而和对象本身脱离了关系,没有多态,也这将给程序留下不可预知的隐患和莫名其妙的BUG


请大家参考另外一篇文章,更底层的描述函数调用:https://blog.csdn.net/u014269285/article/details/80503180

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值