2012-02-03 39 views
2

當從駐留在不同的lib中的鏈接器產生一個解析的外部符號錯誤相同的文件名一個類繼承。想想這個繼承:LIB2 :: MyClass:public LIB1 :: MyClass。類具有相同的文件名在不同庫繼承問題

靜態庫 「LIB1」:

MyClass.h:

namespace LIB1 
{ 

    class MyClass 
    { 
    public: 
     MyClass(); 

     ~MyClass(); 
    }; 
} 

靜態庫 「LIB2」:

MyClass.h:

#include "..\MyClass.h" // Header of MyClass from lib1 somewhere else than this header file 
    namespace LIB2 
    { 

     class MyClass : public LIB1::MyClass 
     { 
     public: 
      MyClass(); 

      ~MyClass(); 
     }; 
    } 

假設兩者。 cpp文件存在。在LIB1

LIB2鏈接

一些可執行文件後,試圖LIB2鏈接和使用派生MyClass的,說

#include "\lib2\MyClass.h" 

int main() 
{ 
    LIB2::MyClass c;    
} 

鏈接失敗,

錯誤LNK2001:無法解析的外部符號「公用: __thiscall LIB1 :: MyClass ::〜MyClass(void)

(與ctor相同)

當我簡單地將其中一個MyClass.cpp的文件名更改爲MyClass1.cpp時,一切都很好。

不是搜索LIB1的定義:在lib1.lib鏈接MyClass的試圖找到他們MyClass.obj(從LIB2)我懷疑。

這種行爲只是感覺太奇怪,是故意。我錯過了什麼?

此外,當在VS2005/2010中設置一個解決方案,包括庫和可執行文件,並讓VS通過Project Properties-> Common Properties-> Framework和References來設置所有lib依賴關係(而不是提供路徑到庫中的鏈接器設置)鏈接成功。

+0

編輯:而不是在lib1.lib搜索LIB1:MyClass的定義鏈接器試圖找到它們在MyClass.obj(從lib2)我懷疑...對不起,忘了那,這沒有任何意義 – 2012-02-03 15:12:17

回答

0

我只是做了在Microsoft Visual C++ 2010速成包含兩個靜態庫項目(LIB1和LIB2),並與你所描述的內容的應用程序項目(主)的解決方案,並能夠重現你的問題。下面是完整的構建輸出我得到:

 
1>------ Build started: Project: lib1, Configuration: Debug Win32 ------ 
1> MyClass.cpp 
1> lib1.vcxproj -> c:\users\samuel windwer\documents\visual studio 2010\Projects\linker_test\Debug\lib1.lib 
2>------ Build started: Project: lib2, Configuration: Debug Win32 ------ 
2> MyClass.cpp 
2> Replacing Debug\MyClass.obj 
2> lib2.vcxproj -> c:\users\samuel windwer\documents\visual studio 2010\Projects\linker_test\Debug\lib2.lib 
3>------ Build started: Project: main, Configuration: Debug Win32 ------ 
3> main.cpp 
3>lib2.lib(MyClass.obj) : error LNK2019: unresolved external symbol "public: __thiscall LIB1::MyClass::MyClass(void)" ([email protected]@@[email protected]) referenced in function "public: __thiscall LIB2::MyClass::MyClass(void)" ([email protected]@@[email protected]) 
3>lib2.lib(MyClass.obj) : error LNK2019: unresolved external symbol "public: __thiscall LIB1::MyClass::~MyClass(void)" ([email protected]@@[email protected]) referenced in function "public: __thiscall LIB2::MyClass::~MyClass(void)" ([email protected]@@[email protected]) 
3>c:\users\samuel windwer\documents\visual studio 2010\Projects\linker_test\Debug\main.exe : fatal error LNK1120: 2 unresolved externals 
========== Build: 2 succeeded, 1 failed, 0 up-to-date, 0 skipped ========== 

消息「更換調試\ MyClass.obj」揭示了這個問題的一些情況。此消息是在構建lib2.lib時由Microsoft的庫管理器(LIB.EXE)發出的。爲了理解這個消息,瞭解一個靜態庫文件(.lib)是什麼以及通過擴展來準確理解LIB.EXE的作用是非常重要的。

第一件事的第一:建立一個靜態庫時沒有代碼實際上是聯繫在一起的。 .lib文件只是一個包含一個或多個.obj文件的歸檔文件。換句話說,.lib文件的目的是提供一種方便的方式將一組.obj文件作爲一個文件分發。 LIB.EXE所做的就是將項目的.obj文件打包到.lib文件中。 LIB.EXE也可以選擇使用.lib文件做其他事情,例如列出所有包含的.obj文件並提取它們;有關更多信息,請參閱MSDN

您的問題指出「lib2中的lib2鏈接」。我假設這意味着,你把lib1.lib在LIB2的項目設置的「附加依賴」,如在此截圖:

enter image description here

爲了準確瞭解加入的.lib文件這樣的靜態庫項目的「附加依賴項」會在更改此設置後執行this answer中的過程以查看運行LIB.EXE以構建lib2.lib時使用的命令行。這裏是:

lib.exe "/OUT:c:\users\samuel windwer\documents\visual studio 2010\Projects\linker_test\Debug\lib2.lib" lib1.lib /LIBPATH:..\Debug Debug\MyClass.obj

此命令生成lib2.lib在命名一個新的靜態庫文件包含所有lib1.lib的.OBJ文件,以及MyClass.obj。 lib1.lib還包含名爲MyClass.obj的對象這一事實是問題的根源。正如LIB.EXE's documentation on MSDN指出:

要使用一個新的對象替換庫成員,指定包含要被替換的構件對象併爲新的對象(或包含它的庫)的文件名的庫。當多個輸入文件中存在具有相同名稱的對象時,LIB會將LIB命令中指定的最後一個對象放入輸出庫中。

「更換調試\ MyClass.obj」該消息被輸出到控制檯時LIB.EXE看到,因爲它認爲的是,第二MyClass.obj應該更換的第一個MyClass.obj的第二個實例。將MyClass.cpp文件中的一個重命名爲MyClass1.cpp可以修復此問題,因爲不再有兩個名爲MyClass.obj的對象文件,因此它們都可以在同一個.lib文件中一起愉快地生活。

看來您已經爲此提出了一些解決方法,但希望您現在瞭解您所看到的行爲。

+0

感謝您關注鏈接。在禁用LIB.exe的/ NOLOGO選項後,我可以看到打包到lib中的對象文件被它們的相對路徑引用。對於MyClass示例,命令行輸出如下所示:** Debug/MyClass.obj替換爲Debug/MyClass.obj **因此,解決方案是將lib1的目標文件保存到不同的位置lib2的。 (DebugLib1/*。obj,DebugLib2/*。obj)然後,lib1的對象可以鏈接到lib2中,而不會在具有相同文件名的情況下衝突對象名稱。 – 2012-02-06 13:08:42

+0

非常歡迎。我很高興我的回答幫助您找到了一個更理想的解決方案來解決您的問題。 – chess007 2012-02-07 00:46:53

相關問題