2012-02-03 9 views
2

異なるライブラリにある同じファイル名を持つクラスから継承すると、リンカは未解決の外部シンボルエラーを発生させます。この継承を考えてみましょう:LIB2 :: MyClass:public LIB1 :: MyClass。異なるファイルの同じファイル名を持つクラス継承問題

静的libに "LIB1":

MyClass.h:

namespace LIB1 
{ 

    class MyClass 
    { 
    public: 
     MyClass(); 

     ~MyClass(); 
    }; 
} 

静的libに "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のを使用しようと、リンクが

エラーLNK2001で失敗

#include "\lib2\MyClass.h" 

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

を言います__thiscall LIB1 :: MyClassの::〜MyClassの(空)

(ctorのために同じ)

MyClass.cppのファイル名をMyClass1.cppに変更するだけで問題ありません。

lib1.libのLIB1:MyClassの定義を検索する代わりに、リンカはそれらをMyClass.obj(lib2から)で見つけようとします。

この動作は、意図的すぎるようにも奇妙に感じます。私は何が欠けていますか?

さらに、libsと実行可能ファイルの両方を含むVS2005/2010のソリューションをセットアップし、VSがプロジェクトのプロパティ - >共通プロパティ - >フレームワークと参照(libのパスをリンカーの設定)リンクが成功します。

+0

EDIT:lib1.libのLIB1:MyClassの定義を検索するのではなく、リンカーはMyClass.obj(lib2から)でそれらを見つけることを試みます。申し訳ありませんが、残念ですが、それは意味をなさない –

答えて

0

2つの静的ライブラリプロジェクト(lib1とlib2)と問題を再現できる内容のアプリケーションプロジェクト(main)を含むMicrosoft Visual C++ 2010 Expressのソリューションを作成しました。

 
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 ========== 

「Debug \ MyClass.objを置き換える」というメッセージは、この問題を明らかにしています。このメッセージは、lib2.libを構築中にMicrosoftのライブラリマネージャ(LIB.EXE)によって生成されました。このメッセージを理解するには、静的ライブラリファイル(.lib)が何であるかを正確に把握し、LIB.EXEの機能拡張を正確に理解することが重要です。

最初のもの:静的ライブラリを構築するときにコードは実際にはリンクされていません。 .libファイルは、内部に1つ以上の.objファイルを含むアーカイブです。つまり、.libファイルの目的は、.objファイルのコレクションを1つのファイルとして配布する便利な方法を提供することです。 LIB.EXEが行うことは、プロジェクトの.objファイルを.libファイルにパッケージ化することだけです。 LIB.EXEには、含まれている.objファイルをすべて一覧表示して抽出するなど、.libファイルで他の処理を行うためのオプションもあります。詳細はMSDNを参照してください。

「lib2はlib1にリンクしています」という質問があります。私がこのスクリーンショットのようにあなたは、LIB2のプロジェクト設定で「追加の依存関係」としてlib1.libと置くことを意味と仮定しています:

enter image description here

の.libファイルなどを追加することを正確に理解するためには、このような静的ライブラリプロジェクトの "Additional Dependency"は、この設定を変更した後、this answerの手順に従ってlib2.libをビルドするためにLIB.EXEを実行するときに使用されるコマンドラインを確認します。ここです:

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

このコマンドは、.objファイルlib1.libと内のファイルだけでなく、MyClass.objのすべてが含まれていlib2.libという名前の新しい静的ライブラリファイルを生成します。 lib1.libにMyClass.objという名前のオブジェクトも含まれているという事実は、あなたの問題の原因です。 LIB.EXE's documentation on MSDNに記載されているとおり:

新しいオブジェクトとライブラリーメンバーを交換するには、メンバーオブジェクト交換すると、新しいオブジェクト(またはそれを含むライブラリ)のファイル名を含むライブラリを指定します。同じ名前のオブジェクトが複数の入力ファイルに存在する場合、LIBはLIBコマンドで指定された最後のオブジェクトを出力ライブラリに置きます。それは第二MyClass.objは最初のものを交換することになっていると思うので、LIB.EXEがMyClass.objの2番目のインスタンスを見たときに「デバッグ\ MyClass.objの交換」

メッセージがコンソールに出力されます。 MyClass.cppファイルの1つをMyClass1.cppに名前を変更すると、MyClass.objという2つのオブジェクトファイルが存在しなくなるため、同じ.libファイルで幸せに一緒に暮らすことができるため、この問題が修正されます。

これはいくつかの回避策をすでに用意しているようですが、現在見ている動作を理解していただければと思います。

+0

リンクありがとうございました。 LIB.exeの/ NOLOGOオプションを無効にすると、libにパッケージ化されているオブジェクトファイルが相対パスで参照されていることがわかりました。 MyClassの例では、コマンドラインの出力は次のようになっていました:** Debug/MyClass.objはDebug/MyClass.objに置き換えられました**したがって、全体としての解決策は、単にlib1のオブジェクトファイルをlib2のもの(DebugLib1/* .obj、DebugLib2/*。obj)そして、lib1のオブジェクトは、同じファイル名を持つオブジェクト名を衝突させずにlib2にリンクすることができます。 –

+0

大歓迎です。私の答えはあなたの問題にもっと望ましい解決策を見出すのに役立ったことをうれしく思っています。 – chess007

関連する問題