靜態綁定和動態綁定
阿新 • • 發佈:2017-09-04
運行期 end bug new sin spa clas clu cout
/**************************************************************************** 靜態綁定:對象在聲明時采用的類型,在編譯期既已確定 動態類型:通常指一個指針或引用目前所指對象的類型,是在運行期決定的 靜態綁定:綁定的是靜態類型,所對應的函數或屬性依賴於對象的靜態類型, 發生在編譯期 動態綁定:綁定的是動態類型,所對應的函數或屬性依賴於對象的動態類型, 發生在運行期 在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函數確實動態綁定. -----------------------------------------------------------------------------*/
靜態綁定和動態綁定