靜態綁定和動態綁定是C++多態性的一種特性。
1、對象的靜態類型和動態類型:
- 對象的靜態類型:
對象在聲明是采用的類型,在編譯期確定;
- 對象的動態類型:
當前對象所指的類型,在運行期決定,對象的動態類型可以更改,但靜態類型無法更改。
1 class B{ 2 3 }; 4 5 class C: public B{ 6 7 }; 8 9 class D: public B{ 10 11 }; 12 13 D* pD=new D(); 14 // pD的靜態類型是它聲明的類型D*,動態類型也是D* 15 B* pB=pD; 16 // pB的靜態類型是它聲明的類型B*,動態類型是pB所指的對象pD的類型D* 17 c* pC=new C(); 18 // pC的靜態類型是它聲明的類型C*,動態類型也是C* 19 pB=pC; 20 // pB的動態類型可以改變,現在它的動態類型為C*
2、靜態綁定和動態綁定
- 靜態綁定:
綁定的是對象的靜態類型,某特性(比如函數)依賴於對象的靜態類型,發生在編譯期。
- 動態綁定:
綁定的是對象的動態類型,某特性(比如函數)依賴於對象的動態類型,發生在運行期。
1 class B{ 2 void DoSomething(); 3 virtual void vfun(); 4 }; 5 6 class C: public B{ 7 //首先說明一下,這個子類重新定義了父類的no-virtual函數,這是一個不好的設計,會導致名稱遮掩;這里只是為了說明動態綁定和靜態綁定才這樣使用。 8 void DoSomething(); 9 virtual void vfun(); 10 }; 11 12 class D: public B{ 13 void DoSomething(); 14 virtual void vfun(); 15 }; 16 17 D* pD=new D(); 18 // pD的靜態類型是它聲明的類型D*,動態類型也是D* 19 B* pB=pD; 20 // 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()。
總結:只有虛函數才使用的是動態綁定,其他的全部是靜態綁定。
當缺省參數和虛函數一起出現的時候情況有點復雜,極易出錯。我們知道,虛函數是動態綁定的,但是為了執行效率,缺省參數是靜態綁定的。
1 class B{ 2 void DoSomething(); 3 virtual void vfun(int i=10); 4 }; 5 6 7 class D: public B{ 8 void DoSomething(); 9 virtual void vfun(int i=20); 10 }; 11 12 D* pD=new D(); 13 // pD的靜態類型是它聲明的類型D*,動態類型也是D* 14 B* pB=pD; 15 // pB的靜態類型是它聲明的類型B*,動態類型是pB所指的對象pD的類型D* 16 pD->vfun(); 17 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.)
轉自:https://www.cnblogs.com/AndyJee/p/4575670.html