动态绑定和静态绑定是为了支持类中的多态。静态和动态分别对应着编译期和运行期。
静态对象:是在编译期就确定了类型,不能改变。
动态对象:在运行期间确定的类型,可以改变其类型。
静态绑定:绑定的是对象的静态类型,某特性(比如函数)依赖于对象的静态类型,发生在编译期。
动态绑定:绑定的是对象的动态类型,某特性(比如函数)依赖于对象的动态类型,发生在运行期
class base{
public:
void fun(){
cout<<"base do something"<<endl;
}
virtual void virfun(){
cout<<"virtual base do something"<<endl;
}
};
class Derived:public base{
public:
void fun(){
cout<<"derived do something"<<endl;
}
virtual void virfun(){
cout<<"virtual derived do something"<<endl;
}
};
int main()
{
Derived *son=new Derived();//son的静态类型是它声明的类型Derived*,动态类型也是Derived*
base *father=son;//father的静态类型是它声明的类型base*,动态类型是father指向对象son的类型Derived*
son->fun();//输出:son do something
father->fun();//输出:father do something
son->virfun();//输出:virtual derived do something
father->virfun();//输出:virtual derived do something
}
从上面的例子可以看出,由于fun函数是非virtual函数,所以也就是编译器会在编译期根据对象的静态类型来选择该函数,比如son的静态类型为Derived,而father的静态类型为base。
而virfun()函数是vitual虚函数,所以在运行期间根据对象的动态类型决定。
注意:
虚函数是动态绑定的,但是参数是静态绑定的,这是出于运行时效率的考虑,如果要动态绑定默认参数,则需要一种类似虚函数表的动态机制。 所以你需要记住默认参数的静态绑定的,否则会引起困惑。来看例子吧:
class Shape{
public:
virtual void draw(int top = 1){
cout<<top<<endl;
}
};
class Rect: public Shape{
public:
virtual void draw(int top = 2){
cout<<top<<endl;
}
};
Rect* rp = new Rect;
Shape* sp = rp;
sp->draw();//输出:2
rp->draw();//输出:1
默认参数的值只和静态类型有关,是静态绑定的。
参考:effective c++ item36、item37