2

別のライブラリにある同じファイル名のクラスから継承する場合、リンカは未解決の外部シンボルエラーを生成します。この継承について考えてみてください:LIB2 :: MyClass:public LIB1::MyClass。

static lib "lib1":

MyClass.h:

namespace LIB1
{

    class MyClass
    {
    public:
        MyClass();

        ~MyClass();
    };
}

static 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を使用しようとします。

#include "\lib2\MyClass.h"

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

リンクはで失敗します

エラーLNK2001:未解決の外部シンボル "public:__thiscall LIB1 :: MyClass ::〜MyClass(void)

(ctorも同じ)

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

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

この振る舞いは、意図的に行うにはあまりにも奇妙に感じます。私は何が欠けていますか?

さらに、ライブラリと実行可能ファイルの両方を含むソリューションをVS2005 / 2010でセットアップし、VSにプロジェクトプロパティ->共通プロパティ->フレームワークと参照を介してすべてのライブラリ依存関係をセットアップさせる場合(リンカー設定でライブラリへのパスを提供する代わりに)リンクは成功します。

4

1 に答える 1

0

Microsoft Visual C++ 2010 Express で、2 つの静的ライブラリ プロジェクト (lib1 と lib2) と、説明した内容のアプリケーション プロジェクト (main) を含むソリューションを作成し、問題を再現することができました。これが私が得る完全なビルド出力です:

1>------ ビルド開始: プロジェクト: lib1、構成: Win32 のデバッグ ------
1> MyClass.cpp
1> lib1.vcxproj -> c:\users\samuel windwer\documents\visual studio 2010\Projects\linker_test\Debug\lib1.lib
2>------ ビルド開始: プロジェクト: lib2、構成: Debug Win32 ------
2> MyClass.cpp
2> Debug\MyClass.obj の置き換え
2> lib2.vcxproj -> c:\users\samuel windwer\documents\visual studio 2010\Projects\linker_test\Debug\lib2.lib
3>------ ビルド開始: プロジェクト: メイン、構成: Win32 のデバッグ ------
3> main.cpp
3>lib2.lib(MyClass.obj): エラー LNK2019: 未解決の外部シンボル "public: __thiscall LIB1::MyClass::MyClass(void)" (??0MyClass@LIB1@@QAE@XZ) 関数 "public: __thiscall LIB2::MyClass::MyClass(void)" (??0MyClass@LIB2@@QAE@XZ)
3>lib2.lib(MyClass.obj): エラー LNK2019: 未解決の外部シンボル "public: __thiscall LIB1::MyClass::~MyClass(void)" (??1MyClass@LIB1@@QAE@XZ) 関数 "public で参照されています: __thiscall LIB2::MyClass::~MyClass(void)" (??1MyClass@LIB2@@QAE@XZ)
3>c:\users\samuel windwer\documents\visual studio 2010\Projects\linker_test\Debug\main.exe: 致命的なエラー LNK1120: 2 つの未解決の外部
========== ビルド: 2 成功、1 失敗、0 最新、0 スキップ ==========

「Replaceing Debug\MyClass.obj」というメッセージは、この問題を明らかにしています。このメッセージは、lib2.lib の構築中に Microsoft の Library Manager (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 を「追加の依存関係」として配置することを意味すると想定しています。

ここに画像の説明を入力

このようにスタティック ライブラリ プロジェクトの「追加の依存関係」として .lib ファイルを追加するとどうなるかを正確に理解するために、この設定を変更した後、この回答の手順に従って、 LIB の実行時に使用されるコマンドラインを確認しました。 lib2.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

このコマンドは、lib1.lib 内のすべての .obj ファイルと MyClass.obj を含む、lib2.lib という名前の新しいスタティック ライブラリ ファイルを生成します。lib1.lib にも MyClass.obj という名前のオブジェクトが含まれているという事実が問題の原因です。MSDN の LIB.EXE のドキュメントに記載されているとおり:

ライブラリ メンバーを新しいオブジェクトに置き換えるには、置き換えるメンバー オブジェクトを含むライブラリと、新しいオブジェクト (またはそれを含むライブラリ) のファイル名を指定します。同じ名前のオブジェクトが複数の入力ファイルに存在する場合、LIB は、LIB コマンドで指定された最後のオブジェクトを出力ライブラリに入れます。

LIB.EXE が MyClass.obj の 2 番目のインスタンスを検出すると、"Replaceing Debug\MyClass.obj" というメッセージがコンソールに出力されます。MyClass.cpp ファイルの 1 つを MyClass1.cpp に名前変更すると、この問題が修正されます。これは、MyClass.obj という名前のオブジェクト ファイルが 2 つなくなるため、両方が同じ .lib ファイル内で問題なく共存できるためです。

すでにいくつかの回避策を考え出されているようですが、表示されている動作を理解していただければ幸いです。

于 2012-02-06T01:54:23.997 に答える