1. 程式人生 > >靜態綁定和動態綁定

靜態綁定和動態綁定

運行期 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函數確實動態綁定.
-----------------------------------------------------------------------------*/

靜態綁定和動態綁定