2014-09-24 24 views
1

我將VS2008中的舊代碼移植到VS2013。該代碼庫的一部分是一個相當複雜的文件記錄庫,它覆蓋了streambuf並將其與fstream關聯。它通過streambuf和fstream的繼承來實現這一點。覆蓋fstream的streambuf

但是,當我嘗試將生成的DLL與使用它,我得到另一個DLL鏈接:

1>syscored.lib(syscored.dll) : error LNK2005: "public: void __thiscall 
std::basic_fstream<char,struct std::char_traits<char> >::close(void)" 
([email protected][email protected][email protected]@[email protected]@@[email protected]@QAEXXZ) already 
defined in iptsrvfl.obj 
1>syscored.lib(syscored.dll) : error LNK2005: 
"public: void __thiscall std::basic_fstream<char,struct 
std::char_traits<char> >::`vbase destructor'(void)" 
([email protected][email protected]@[email protected]@@[email protected]@QAEXXZ) already 
defined in iptsrvfl.obj 

基本上,從fstream的繼承導致該DLL導出一些fstream的的符號。我使用該DLL的類也使用標準fstream實例,close()和dtor()的符號被視爲已經定義。

我試着改變fstream派生類來使用遏制而不是繼承,但是沒有辦法將自定義streambuf與包含的流關聯起來。它根本不通過公共界面暴露。 (我們在fstream的ctor中調用init(streambuf))。

有人可以告訴我: 1)如何將streambuf與包含的fstream相關聯,或者2)如何避免此符號衝突。

謝謝。

+0

「streambuf和fstream的繼承」。相同的類是否同時繼承streambuf和fstream或兩個不同的類? – 2014-09-24 14:16:05

+0

兩個不同的類。 streambuf派生類並不是我的問題。問題是我如何將它與fstream聯繫起來。 – dviljoen 2014-09-24 14:29:58

+0

看起來傳統代碼正在通過本書做正確的事情。沒有看到任何問題。顯示你如何鏈接你的DLL(完整的鏈接器命令)。 – 2014-09-24 14:40:19

回答

1

如果導出的類從未顯式導出的模板實例化繼承,則編譯器會隱式導出此模板實例化。 Source。你不想這樣做,因爲它會導致你看到的精確類型的錯誤。

所以你不應該像你所做的那樣導出你的記錄器類。事實上,你應該很少出口課程。如果您需要在您的DLL之外製作實例,請導出類工廠(一個函數)。僅當您希望其他人從中繼承時才導出類,並且不要導出任何類型的任何模板。您可以導出特定的模板實例。

如果您需要繼承標準庫模板,並希望其他人繼續繼續您的類,則可能必須將其設置爲僅包含頭文件的全內聯類,或者可以選擇性地導出其方法,而不是類本身。

+0

謝謝。很好解釋。 – dviljoen 2014-09-25 13:12:27

0

您或許可以通過鏈接到CRT DLL來避免符號衝突。只有在編譯獨立EXE或者不導出任何標準C++類型(即純C接口或COM DLL)的DLL時,靜態鏈接纔有意義。

+0

我不確定靜態鏈接是什麼意思。我鏈接到生成的DLL的導入庫。 – dviljoen 2014-09-24 14:35:14

+0

你正在動態鏈接你的**你的DLL。你如何鏈接到CRT?/MT還是/ MD? – MSalters 2014-09-24 14:43:23

+0

我正在使用/ MD和/ MDd – dviljoen 2014-09-24 15:01:26