首先來看一下一個繼承
// brass.h -- bank accound classes<br />#ifndef BRASS_H_<br />#define BRASS_H_</p><p>// Brass Account Class<br />class Brass<br />{<br />private:<br />enum { MAX = 35 };<br />char fullName[MAX];<br />long acctNum;<br />double balance;<br />public:<br />Brass(const char *s = "NullBody", long an = -1,<br />double bal = 0.0);<br />void Deposit(double amt);<br />virtual void WithDraw(double amt);<br />double Balance() const;<br />virtual void ViewAcct() const;<br />virtual ~Brass() {}<br />};</p><p>// Brass Plus Account Class<br />class BrassPlus : public Brass<br />{<br />private:<br />double maxLoan;<br />double rate;<br />double owesBank;<br />public:<br />BrassPlus(const char *s = "NullBody", long an = -1,<br />double bal = 0.0, double m1 = 500, double r = 0.10);<br />BrassPlus(const Brass &ba, double m1 = 500, double r = 0.10);<br />virtual void ViewAcct() const;<br />virtual void WithDraw(double amt);<br />void ResetMax(double m) { maxLoan = m; }<br />void ResetRate(double r) { rate = r; }<br />void ResetOwes() { owesBank = 0; }<br />};</p><p>#endif
Brass類在聲明ViewAcct()和Withdraw()時使用了virtual,這有什麼用呢?
如果方法是通過引用或指標而不是對象調用的,它將確定使用哪一種方法,我們知道在類的繼承中,基類指標可以在不進行顯式類型轉換情況下指向衍生類別對象;基類引用可以在不進行顯式類型轉換的情況引用衍生類別對象。如果沒有使用virtual關鍵字,程式將根據參考型別或指標類型選擇方法;如果使用了virtual,程式將根據引用或指標指向的對象的類型來選擇方法。如果ViewAcct不是虛擬,則程式的行為如下:// behavior with non-virtual ViewAcct()<br />// method chosen according to reference type<br />Brass dom("Dominic Banker", 11224, 4183.5);<br />BrassPlus dot("Dorothy Banker", 12118, 2529.00);<br />Brass &b1_ref = dom;<br />Brass &b2_ref = dot;<br />b1_ref.ViewAcct(); // use Brass::ViewAcct()<br />b2_ref.ViewAcct(); // use Brass::ViewAcct()
引用變數類型為:Brass,所以選擇了Brass::ViewAccount()。使用Brass指標代替引用時,行為與之類似。
如果ViewAcct()是虛擬,則行為如下:
// behavior with virtual ViewAcct()<br />// method chosen according to object type<br />Brass dom("Dominic Banker", 11224, 4183.45);<br />BrassPlus dot("Dorothy Banker", 12118, 2592.00);<br />Brass &b1_ref = dom;<br />Brass &b2_ref = dot;</p><p>b1_ref.ViewAcct(); // use Brass::ViewAcct()<br />b2_ref.ViewAcct(); // use BrassPlus::ViewAcct()
這裡兩個引用的類型都是Brass,但b2_ref引用的是一個BrassPlus對象,所以使用的是BrassPlus::ViewAcct()。使用Brass指標代替引用時,行為將類似。
方法在基類中被聲明為虛擬後,它在衍生類別中將自動成為虛方法。不過,在衍生類別聲明中使用關鍵字virtual來指明哪些函數是虛函數也不失為一個好方法。
基類聲明了一個虛擬解構函式。這樣做是為了確保釋放派生對象時,按正確的順序調用解構函式。