首先看一下代码:
//============================================================================
// 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.youkuaiyun.com/u014269285/article/details/80503180