effective C++筆記之條款39: 避免“向下轉換”繼承層次

  • 先看如下例子:

class Person {…};
class BankAccount
{
public:
         BankAccount(const Person *primaryOwner, const Person *jointOwner);
         virtual ~BankAccount();
         virtual void makeDeposit(double amount)= 0;
         virtual void makeWithdrawal(doubleamount) = 0;
         virtual double balance() const = 0;
         …
};
class SavingsAccount : public BankAccount
{
public:
        SavingsAccount(constPerson *primaryOwner, const Person *jointOwner);
         ~SavingsAccount();
         void creditInterest();   //給賬戶增加利息
                   …
 };

 假設爲所有賬戶維持一個列表,通過list類模板實現。

         list<BankAccount*>allAccount;   //銀行中所有賬戶

         現在準備寫一段代碼來遍歷所有賬戶,爲每個賬戶計算利息。如下所示代碼:

         for(list<BankAccount*>::iterator p = allAccount.begin(); p != allAccounts.end();++p)

                  (*p)->creditInterest();  //錯誤

         因爲creditInterest只是爲SavingsAccount對象聲明的,而不是BankAccount。

        

  • 向下轉換:從一個基類指針到一個派生類指針。向下轉換了繼承的層次結構。
  •  通過向下轉換可以得到通過編譯,並正常運行。(static_cast<SavingsAccount *>(*p)->creditInterest();)但是對以後的擴充類難以維護。向下轉換難看、容易導致錯誤,而且使得代碼難於理解、升級和維護。
  •  向下轉換可以通過如下兩種方法消除:
  1.  最好的方法是將這種轉換用虛函數調用來代替,同時,它可能對有些類不適用,所以要使這些類的每個虛函數成爲一個空操作
  2. 加強類型約束,使得指針的聲明類型和你所知道的真的指針類型之間沒有出入。
  • 當不得不進行向下轉換時,可以採用比原始轉換更好的辦法。這種方法稱爲“安全的向下轉換”,通過dynamic_cast運算符來實現。當對一個指針使用dynamic_cast時,先嚐試轉換,如果成功(即指針的動態類型和正被轉換的類型一致),就返回新類型的合法指針;如果dynamic_cast失敗,返回空指針。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章