C++多繼承中重寫不同基類中相同原型的虛函數

來源:互聯網
上載者:User

     在C++多繼承體系當中,在衍生類別中可以重寫不同基類中的虛函數。下面就是一個例子:

  1. class CBaseA
  2. {
  3. public:
  4.     virtual void TestA();
  5. };
  6. class CBaseB
  7. {
  8. public:
  9.     virtual void TestB();
  10. };
  11. class CDerived : public CBaseA, public CBaseB
  12. {
  13. public:
  14.     virtual void TestA(); // 重寫基類CBaseA中的虛函數TestA()
  15.     virtual void TestB(); // 重寫基類CBaseB中的虛函數TestB()
  16. };
  17. void Test()
  18. {
  19.     CDerived D;
  20.     CBaseA *pA = &D;
  21.     CBaseB *pB = &D;
  22.     pA->TestA(); // 調用類CDerived的TestA()函數
  23.     pB->TestB(); // 調用類CDerived的TestB()函數
  24. }

    可是,如果兩個基類中有一個相同原型的虛函數,例如下面這樣:

  1. class CBaseA
  2. {
  3. public:
  4.     virtual void Test();
  5. };
  6. class CBaseB
  7. {
  8. public:
  9.     virtual void Test();
  10. };

    怎樣在衍生類別中重寫這兩個相同原型的虛函數呢?
    也許這種情況並不常見,可是這種情況卻確實存在。比如說開發的時候使用的兩個類庫是不同的廠商提供的,或者說這兩個類庫是由公司的不同開發小組開發的。對前者來說,修改基類的介面是不可能的;對後者來說,修改介面的代價很大。
    如果在衍生類別中直接重寫這個虛函數,那麼2個基類的Test()虛函數都將被覆蓋。這樣的話就只能有一個Test()的實現,而不是像前面的例子那樣有不同的實現。

  1. class CDerived : public CBaseA, public CBaseB
  2. {
  3. public:
  4.     virtual void Test();
  5. };
  6. void Test()
  7. {
  8.     CDerived D;
  9.     CBaseA *pA = &D;
  10.     CBaseB *pB = &D;
  11.     // 下面2行代碼都將調用類CDerived的Test()函數
  12.     pA->Test();
  13.     pB->Test(); 
  14. }

    為了實現第一個例子中的那樣,在衍生類別CDerived中重寫不同基類中相同原型的虛函數Test(),可以使用下面的方法。
    首先,不需要對2個基類進行任何修改(在實際的開發當中,修改基類的可能性非常小)。

  1. class CBaseA
  2. {
  3. public:
  4.     virtual void Test();
  5. };
  6. class CBaseB
  7. {
  8. public:
  9.     virtual void Test();
  10. };

    現在,為這個繼承體系添加2個中間類,分別從2個基類派生。

  1. class CMiddleBaseA : public CBaseA
  2. {
  3. private:
  4.     // 真正的實現函數
  5.     // 設定為純虛函數,在衍生類別裡必須實現
  6.     virtual void CBaseA_Test() = 0;
  7.     // 改寫繼承下來的虛函數
  8.     // 僅僅直接調用真正的實現函數
  9.     virtual void Test() 
  10.     { 
  11.         CBaseA_Test(); 
  12.     }
  13. };
  14. // 與類CMiddleBaseA採用相同的方法
  15. class CMiddleBaseB : public CBaseB
  16. {
  17. private:
  18.     virtual void CBaseB_Test() = 0;
  19.     virtual void Test() 
  20.     { 
  21.         CBaseB_Test(); 
  22.     }
  23. };

    然後,類CDerived以上面2個中間類作為基類來派生。分別重寫上面2個基類中原型不同的純虛函數,添加不同的實現代碼。

  1. class CDerived : public CMiddleBaseA, public CMiddleBaseB
  2. {
  3. private:
  4.     // 重寫從中間類繼承下來的虛函數
  5.     virtual void CBaseA_Test(); // 這裡實際上是重寫CBaseA的Test()
  6.     virtual void CBaseB_Test(); // 這裡實際上是重寫CBaseB的Test()
  7. };
  8. void Test()
  9. {
  10.     CDerived D;
  11.     CBaseA *pA = &D;
  12.     CBaseB *pB = &D;
  13.     // 調用類CBaseA的Test()函數
  14.     // 由於C++多態的特性,實際上調用的是類CDervied中的CBaseA_Test()函數
  15.     pA->Test(); 
  16.     // 調用類CBaseB的Test()函數
  17.     // 由於C++多態的特性,實際上調用的是類CDervied中的CBaseB_Test()函數
  18.     pB->Test();
  19. }

    現在以上面代碼中的pA->Test();這行代碼來說明上面的方案是怎麼實現的。
    首先,由於虛函數Test()在類CBaseA的衍生類別CMiddleBaseA中被重寫,所以這行代碼會去調用類CMiddleBaseA的Test()函數;
    然後,類CMiddleBaseA的Test()函數會去調用實現函數CBaseA_Test();
    最後,由於虛函數CBaseA_Test()在類CMiddleBaseA的衍生類別CDerived中被重寫,所以真正調用的是類CDerived中的CBaseA_Test()函數。
    同樣的道理,代碼pB->Test();實際上調用的是類CDervied中的CBaseB_Test()函數。
    通過上面的方法就可以在C++多繼承中重寫不同基類中相同原型的虛函數。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.