歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

當C++多繼承遇上類型轉換

1 由來

客戶用陳舊的VC++6.0進行項目開發,有一塊功能需要我來實現。讓一個早就習慣了VS2013的人去使用C++支持不太好的VC6去做開發實在是非常不爽,於是另辟蹊徑,打算使用VC++2013開發編譯出DLL,供VC6下調用即可。使用C++開發DLL的基本原則是減少暴露和接口簡單化,最常用的方式就是使用純虛類導出接口。另一種就是使用C++實現,但是導出時只導出C函數。處於使用的便利性考慮,采用了第一種方式。

C++ Primer Plus 第6版 中文版 清晰有書簽PDF+源代碼 http://www.linuxidc.com/Linux/2014-05/101227.htm

讀C++ Primer 之構造函數陷阱 http://www.linuxidc.com/Linux/2011-08/40176.htm

讀C++ Primer 之智能指針 http://www.linuxidc.com/Linux/2011-08/40177.htm

讀C++ Primer 之句柄類 http://www.linuxidc.com/Linux/2011-08/40175.htm

C++11 獲取系統時間庫函數 time since epoch http://www.linuxidc.com/Linux/2014-03/97446.htm

C++11中正則表達式測試 http://www.linuxidc.com/Linux/2012-08/69086.htm

2 原型與問題

基本的設計思路可以用如下代碼描述。

#include <iostream>
#include <hash_map>
using namespace std;


class I1
{
public:
 virtual void vf1()
 {
  cout << "I'm I1:vf1()" << endl;
 }
};


class I2
{
public:
 virtual void vf2()
 {
  cout << "I'm I2:vf2()" << endl;
 }
};


class C : public I1, public I2
{
private:
 hash_map<string, string> m_cache;
};


I1* CreateC()
{
 return new C();
}


int main(int argc, char** argv)
{
 I1* pI1 = CreateC();
 pI1->vf1();


 I2* pI2 = (I2*)pI1;
 pI2->vf2();


 delete pI1;
 return 0;
}

采用基於接口的設計方法,對外只暴露接口類I1和I2,對於實際的實現類C則對外隱藏。客戶在使用的時候,只需要調用CreateC()就可以產生C類型的對象,而不必知道C的實現細節。然後通過不同的接口調用不同方面的功能。看起來一切還可以,但實際運行卻是有問題的,上述代碼執行結果如下:

第二行的輸出對應pI2->vf2(),顯然結果是錯誤的,調用者的本意是調用I2::vf2(),實際卻調用了I1::vf1()。隨後我發現這個問題其實在論壇上也有人提出過,也有不少人給出了答案,但是感覺解釋的不夠明確和詳細,所以決定親自一探究竟。

更多詳情見請繼續閱讀下一頁的精彩內容: http://www.linuxidc.com/Linux/2014-05/101576p2.htm

Copyright © Linux教程網 All Rights Reserved