静态绑定和动态绑定
/**************************************************************************** 静态绑定:对象在声明时采用的类型,在编译期既已确定 动态类型:通常指一个指针或引用目前所指对象的类型,是在运行期决定的 静态绑定:绑定的是静态类型,所对应的函数或属性依赖于对象的静态类型, 发生在编译期 动态绑定:绑定的是动态类型,所对应的函数或属性依赖于对象的动态类型, 发生在运行期 在C++中,非虚函数一般都是静态绑定,而虚函数都是动态绑定(如此才可实现多态性) ****************************************************************************/ #if 0 #include <iostream> class A { public: void func() { std::cout<<"A::func()\n"; } }; class B : public A { public: void func() { std::cout<<"B::func()\n"; } }; class C : public A { public: void func() { std::cout<<"C::func()\n"; } }; int main() { C* pc = new C(); //pc的静态绑定类型和动态绑定类型均为C* B* pb = new B(); //pb的静态绑定和动态绑定类型均为B* A* pa = pc; //pa的静态绑定类型为A*,动态绑定类型为pc的类型C* pa = pb; //将pa的动态绑定类型改为B*,其静态绑定类型仍为A* C* pNull = NULL; //pNull静态绑定类型为C* pa->func(); pc->func(); pNull->func(); return 0; } #endif /*---------------------------------------------------------------------- 结论: 1.如果基类A中的func函数不是虚函数,无论哪个指针对func的调用都是 在定义时的静态类型决定,早在编译期确定了. 2.同样空指针也能调用非虚函数而不报错,所以要做空指针检查,因此静 态绑定不能实现多态。 3.如果基类中的func函数是虚函数,那所有的调用都要等到运行是根据其 指向对象的类型才能确定,比起静态绑定自然是要有性能损失,但实现了多态。 4.引用同样适用。 建议: 绝对不要重新定义继承而来的非虚函数,因为这样导致函数调用由对象声明的 静态类型确定了,而和对象本身脱离了关系,没有多态,这也将给程序留下预知的 隐患和莫名奇妙的BUG. 在动态绑定中,要注意默认参数的使用,当缺省参数和virtual函数一起使用时, 一定要谨慎。 -------------------------------------------------------------------------*/ # include <iostream> using namespace std; class F { public: virtual void func(int i = 1) { cout<<"F::func()"<<i<<endl; } }; class E : public F { public: virtual void func(int i = 0) { cout<<"E::func()"<<i<<endl; } }; void main() { F* pf = new F(); E* pe = new E(); pf->func(); //F::func()1 pf = pe; //将pf的动态绑定类型改为E* pf->func(); //E::func()1 } /*---------------------------------------------------------------------------- 注意: 绝对不要重新定义一个继承而来的virtual函数的缺省参数值,因为缺省参数值都是 静态绑定的,而virtual函数确实动态绑定. -----------------------------------------------------------------------------*/ <wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">