【问题标题】:Classes with same file name in different libs inheritance issue不同库继承问题中具有相同文件名的类
【发布时间】:2012-02-03 15:07:32
【问题描述】:

当从位于不同库中的具有相同文件名的类继承时,链接器会产生未解决的外部符号错误。想想这个继承: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: 无法解析的外部符号“public: __thiscall LIB1::MyClass::~MyClass(void)

(与ctor相同)

当我简单地将其中一个 MyClass.cpp 的文件名更改为 MyClass1.cpp 时,一切都很好。

链接器不是在 lib1.lib 中搜索 LIB1:MyClass 的定义,而是尝试在 MyClass.obj(来自 lib2)中找到它们,我怀疑。

这种行为感觉太奇怪了,不可能是故意的。我错过了什么?

此外,当在 VS2005/2010 中设置解决方案时,包括库和可执行文件,并让 VS 通过项目属性->通用属性->框架和引用设置所有库依赖项(而不是在链接器设置)链接成功。

【问题讨论】:

  • 编辑:链接器不是在 lib1.lib 中搜索 LIB1:MyClass 的定义,而是尝试在 MyClass.obj 中找到它们(来自 lib2)我怀疑......对不起,忘记了,那没有没有任何意义

标签: c++ inheritance static unresolved-external


【解决方案1】:

我刚刚在 Microsoft Visual C++ 2010 Express 中制作了一个解决方案,其中包含两个静态库项目(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,配置:调试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> 主.cpp 3>lib2.lib(MyClass.obj) : error LNK2019: unresolved external symbol "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) : error LNK2019: unresolved external symbol "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 unresolved externals ========== 构建:2 成功,1 失败,0 最新,0 跳过 ==========

消息“Replaceing Debug\MyClass.obj”阐明了这个问题。此消息由 Microsoft 的库管理器 (LIB.EXE) 在构建 lib2.lib 时发出。为了理解此消息,重要的是要准确了解静态库文件 (.lib) 是什么,以及通过扩展了解 LIB.EXE 的作用。

第一件事:在构建静态库时实际上没有链接任何代码。 .lib 文件只是一个存档,其中包含一个或多个 .obj 文件。换句话说,.lib 文件的目的是提供一种方便的方式将 .obj 文件集合作为一个文件进行分发。 LIB.EXE 所做的只是将项目的 .obj 文件打包成一个 .lib 文件。 LIB.EXE 也有对 .lib 文件做其他事情的选项,例如列出所有包含的 .obj 文件并提取它们;请参阅MSDN 了解更多信息。

您的问题指出“lib1 中的 lib2 链接”。我假设这意味着您将 lib1.lib 作为“附加依赖项”放在 lib2 的项目设置中,如下图所示:

为了准确了解添加 .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 命令中指定的最后一个对象放入输出库中。

当 LIB.EXE 看到 MyClass.obj 的第二个实例时,消息“Replaceing Debug\MyClass.obj”会打印到控制台,因为它认为第二个 MyClass.obj 应该替换第一个。将其中一个 MyClass.cpp 文件重命名为 MyClass1.cpp 可以解决此问题,因为不再有两个名为 MyClass.obj 的目标文件,因此它们可以在同一个 .lib 文件中愉快地生活在一起。

您似乎已经为此想出了一些解决方法,但希望您现在了解您所看到的行为。

【讨论】:

  • 感谢您提供链接。禁用 LIB.exe 的 /NOLOGO 选项后,我可以看到打包到 lib 中的目标文件由它们的相对路径引用。对于 MyClass 示例,命令行输出类似于:Debug/MyClass.obj 替换为 Debug/MyClass.obj 所以解决整个问题的方法是简单地将 lib1 的目标文件保存到与 lib2 不同的位置。 (DebugLib1/*.obj, DebugLib2/*.obj) 然后,lib1 的对象可以链接到 lib2,而不会在具有相同文件名的情况下发生对象名称冲突。
  • 不客气。很高兴我的回答帮助您找到了更理想的解决方案。
猜你喜欢
  • 2015-07-18
  • 2011-01-24
  • 1970-01-01
  • 2011-05-29
  • 2017-07-07
  • 2011-01-15
  • 1970-01-01
  • 2011-02-07
  • 1970-01-01
相关资源
最近更新 更多