为了支持C++的多态性,才用了动态绑定与静态绑定。
静态类型与动态类型
- 对象的静态类型:
对象在声明时候的类型,是在编译时期确定的。
- 对象的动态类型:
目标所指向的对象,是在运行期决定的。对象的动态类型可以更改,但是静态类型无法更改。
示例:
class B
{
}
class C : public B
{
}
class D : public B
{
}
D* pD = new D();//pD的静态类型是它声明的类型D*,动态类型也是D*
B* pB = pD;//pB的静态类型是它声明的类型B*,动态类型是pB所指向的对象pD的类型D*
C* pC = new C();
pB = pC;//pB的动态类型是可以更改的,现在它的动态类型是C*
静态绑定与动态绑定
- 静态绑定:
绑定的是静态类型,比如函数依赖于对象的静态类型,发生在编译期。
- 动态绑定:
绑定的是动态类型,比如函数依赖于对象的动态类型,发生在运行期。
示例:
class B
{
void DoSomething();
virtual void vfun();
}
class C : public B
{
void DoSomething();//首先说明一下,这个子类重新定义了父类的no-virtual函数,这是一个不好的设计,会导致名称遮掩;这里只是为了说明动态绑定和静态绑定才这样使用。
virtual void vfun();
}
class D : public B
{
void DoSomething();
virtual void vfun();
}
D* pD = new D();
B* pB = pD;
pD -> DoSomething();//(1)
pB -> DoSomething();//(2)
pD -> vfun();//(3)
pB -> vfun();//(4)
- (1) 和 (2) 调用的是
不同
的函数。
因为DoSomething函数不是虚函数,是静态绑定的,在编译器时期会根据对象的类型选择函数。
pD的静态类型是D*,pB的静态类型是B*。所以(1)调用的是D::DoSomething();(2)调用的是B::DoSmething()。
- (3)和(4)调用的是
相同
的函数。
因为vfun函数是虚函数,是动态绑定的,绑定的是对象的动态类型。
pB虽然和pD的静态类型不同,但是他们指向同一个对象,动态类型是相同的,都是D*。所以调用的都是D::vfun()。
总结:
只有虚函数才有动态绑定,其他的都是静态绑定。
缺省参数与虚函数
虚函数是动态绑定的,缺省参数是静态绑定的。
示例:
class B
{
virtual void vfun(int i = 10);
}
class D : public B
{
virtual void vfun(int i = 20);
}
D* pD = new D();
B* pB = pD;
pD->vfun();//a
pB->vfun();//b
a与b 调用的都是D::vfun(),但是缺省参数是自己各自静态类型的。
绝不重新定义继承而来的缺省参数