1. 程式人生 > >C++ 實用泛型程式設計之 虛擬函式(C++ virtual function)雜談

C++ 實用泛型程式設計之 虛擬函式(C++ virtual function)雜談

一 C++虛擬函式(C++ virtual function)雜談

我們在程式設計的時候,經常會遇到這樣的情況,假設有兩個物件,你要在函式中分別呼叫它們的OnDraw方法,我們以前的做法一般是這樣的。

void f(int iType)

{

 switch(iType)

 {

 case 1:

  //CCircle OnDraw

  break;

 case 2:

  //CRectangle OnDraw

  break;

 }

}

這種方法當然能解決我們的問題,但是如果有新的型別要增加,它就必須要往下加程式碼才行了,這樣函式裡的程式碼會越寫越長。你可能會想我的型別不多,往下加也不會太長,但是這種想法是不可取的,因為實際工作當中,我們經常遇到的情況是,一個系統可能要維護好幾年,甚至10

幾年都會有,所以不可預知的事情很多,做設計的時候不能有這種僥倖心裡。C++中提供了虛擬函式,可以方便我們解決這個問題。

class CShape

{

public:

 virtual void OnDraw(){}

};

class CCircle:public CShape

{

public:

 void OnDraw()

 {

  cout<<"CCircle OnDraw"<<endl;

 }

};

class CRectanglepublic CShape

{

 void OnDraw()

 {

  cout<<"CRectangle OnDraw"

<<endl;

 }

};

定義一個介面函式,把基類作為型參,物件傳入後就可以呼叫到對應的函數了。

void SelfDraw(CShape *_shap)

{

 _shap->OnDraw();

}

在呼叫的時候只需要寫類似如下的程式碼。

CCircle c1;

CRectangle r1;

SelfDraw(&c1);

SelfDraw(&r1);

程式編譯執行後的結果如下。

 


可能剛學c++不久的朋友不知道為什麼可以這樣使用,為什麼基類可以正確的呼叫到子類的函式,那麼讓我們來看看祕密到底在哪裡吧。

 


祕密就是__vfptr(virtual function pointer)

__vfptr是一個指標陣列指向虛擬函式,當CCircle物件傳入基類指標後,虛擬函式指標會指向CCircle過載的OnDraw函式,所以我們就會看到SelfDraw中_shap->OnDraw()可以正確呼叫到它對應子類函數了。