天天看點

(C++)C++多态性中的靜态綁定和動态綁定

靜态綁定和動态綁定是C++多态性的一種特性。

1、對象的靜态類型和動态類型:

  • 對象的靜态類型:

對象在聲明是采用的類型,在編譯期确定;

  • 對象的動态類型:

目前對象所指的類型,在運作期決定,對象的動态類型可以更改,但靜态類型無法更改。

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();
// pC的靜态類型是它聲明的類型C*,動态類型也是C*
pB=pC;
// pB的動态類型可以改變,現在它的動态類型為C*
           

2、靜态綁定和動态綁定

  • 靜态綁定:

綁定的是對象的靜态類型,某特性(比如函數)依賴于對象的靜态類型,發生在編譯期。

  • 動态綁定:

綁定的是對象的動态類型,某特性(比如函數)依賴于對象的動态類型,發生在運作期。

class B{
    void DoSomething();
    virtual void vfun();
};

class C: public B{
    //首先說明一下,這個子類重新定義了父類的no-virtual函數,這是一個不好的設計,會導緻名稱遮掩;這裡隻是為了說明動态綁定和靜态綁定才這樣使用。  
    void DoSomething();
    virtual void vfun();
};

class D: public B{
    void DoSomething();
    virtual void vfun();
};

D* pD=new D();
// pD的靜态類型是它聲明的類型D*,動态類型也是D*
B* pB=pD;
// pB的靜态類型是它聲明的類型B*,動态類型是pB所指的對象pD的類型D*
           

pD->DoSomething()和pB->DoSomething()調用的是同一個函數嗎?

答案:不是的,雖然pD和pB指向同一對象,但函數DoSomething是一個non-virtual函數,它是靜态綁定的,也就是編譯器會在編譯器根據對象的靜态類型來選擇函數,pD的靜态類型是D*,那麼編譯器在處理pD->DoSomething()的時候會将它指向D::DoSomething()。同理,pB的靜态類型是B*,那麼pB->DoSomething()調用的就是B::DosSomething()。

pD->vfun()和pB->vfun()調用的是同一函數嗎?

答案:是的,vfun是個虛函數,它是動态綁定的,也就是它綁定的是對象的動态類型,pB和pD雖然靜态類型不同,但他們同時指向一個對象,他們的動态對象是相同的,都是D*,是以,他們調用的是同一個函數:D::vfun()。

上面都是針對對象指針的情況,對于引用(reference)的情況同樣适用。

指針和引用的動态類型和靜态類型可能會不一緻,但是對象的動态類型和靜态類型是一緻的。

D D;

D.DoSomething()和D.vfun()永遠調用的都是D::DoSomething()和D::vfun()。

總結:隻有虛函數才使用的是動态綁定,其他的全部是靜态綁定。

當預設參數和虛函數一起出現的時候情況有點複雜,極易出錯。我們知道,虛函數是動态綁定的,但是為了執行效率,預設參數是靜态綁定的。

class B{
    void DoSomething();
    virtual void vfun(int i=10);
};


class D: public B{
    void DoSomething();
    virtual void vfun(int i=20);
};

D* pD=new D();
// pD的靜态類型是它聲明的類型D*,動态類型也是D*
B* pB=pD;
// pB的靜态類型是它聲明的類型B*,動态類型是pB所指的對象pD的類型D*
pD->vfun();
pB->vfun();
           

有上面的分析可知,pD->vfun()和pB->vfun()調用都是函數D::vfun(),但是他們的預設參數是多少?

分析一下,預設參數是靜态綁定的,pD->vfun(),pD的靜态類型是D*,是以它的預設參數是20;而pB的靜态類型是B*,是以pB->vfun()的預設參數是10.

對于這個特性,估計沒有人會喜歡。是以,永遠記住:

“絕不重新定義繼承而來的預設參數(Never redefine function’s inherited default parameters value.)”

參考文章:

http://blog.csdn.net/chgaowei/article/details/6427731