提问人:Tim Handschack 提问时间:2/3/2012 更新时间:2/7/2012 访问量:1570
不同库中具有相同文件名的类继承问题
Classes with same file name in different libs inheritance issue
问:
当从位于不同库中的具有相同文件名的类继承时,链接器会产生未解决的外部符号错误。想想这个继承: 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 通过项目属性->通用属性->框架和引用设置所有库依赖项(而不是在链接器设置中提供库的路径),链接成功。
答:
我刚刚在 Microsoft Visual C++ Express 中制作了一个解决方案,其中包含两个静态库项目(lib1 和 lib2)和一个应用程序项目(main),其中包含您描述的内容,并且能够重现您的问题。这是我得到的完整构建输出:
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)" (??0MyClass@LIB1@@QAE@XZ) referenced in function "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) referenced in function "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 : fatal error LNK1120: 2 unresolved externals ========== Build: 2 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
消息“Replacing 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 文件添加为静态库项目的“附加依赖项”有什么作用,在更改此设置后,我按照此答案中的过程查看运行 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在MSDN上的文档:
若要将库成员替换为新对象,请指定包含要替换的成员对象的库以及新对象(或包含该对象的库)的文件名。当多个输入文件中存在同名对象时,LIB 会将 LIB 命令中指定的最后一个对象放入输出库中。
当 LIB.EXE 看到 MyClass.obj 的第二个实例时,消息“正在替换 Debug\MyClass.obj”将打印到控制台,因为它认为第二个 MyClass.obj 应该替换第一个实例。将其中一个 MyClass.cpp 文件重命名为 MyClass1.cpp 可解决此问题,因为不再有两个名为 MyClass.obj 的对象文件,因此它们可以在同一个 .lib 文件中愉快地共存。
似乎您已经为此提出了一些解决方法,但希望您现在了解您所看到的行为。
评论
上一个:链接:未解析的外部(源于多态性)
下一个:继承接口时未解析的符号
评论