C++ 不同libs继承问题中具有相同文件名的类

C++ 不同libs继承问题中具有相同文件名的类,c++,inheritance,static,unresolved-external,C++,Inheritance,Static,Unresolved External,当从具有相同文件名且驻留在不同库中的类继承时,链接器会产生未解析的外部符号错误。考虑这个继承:LIB2::MyClass:public LIB1::MyClass 静态lib1: MyClass.h: namespace LIB1 { class MyClass { public: MyClass(); ~MyClass(); }; } #include "..\MyClass.h" // Header of MyC

当从具有相同文件名且驻留在不同库中的类继承时,链接器会产生未解析的外部符号错误。考虑这个继承:LIB2::MyClass:public LIB1::MyClass

静态lib1:

MyClass.h:

namespace LIB1
{

    class MyClass
    {
    public:
        MyClass();

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

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

            ~MyClass();
        };
    }
静态lib2:

MyClass.h:

namespace LIB1
{

    class MyClass
    {
    public:
        MyClass();

        ~MyClass();
    };
}
    #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:\uu thiscall LIB1::MyClass::~MyClassvoid

同样适用于ctor

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

链接器没有在LIB1.lib中搜索LIB1:MyClass的定义,而是尝试在lib2的MyClass.obj中找到它们

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


<> P>此外,在VS2005/2010中建立一个解决方案,包括LIBS和可执行文件,并且VS通过项目属性设置所有LIB依赖项->通用属性>框架和引用,而不是在链接器设置中提供链接到链接的成功路径。

< P>我在微软Visual C++中只做了一个解决方案。2010 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 ========== 替换Debug\MyClass.obj的消息说明了这个问题。此消息是由Microsoft的Library Manager LIB.EXE在生成lib2.LIB时发出的。为了理解此消息,必须准确了解静态库文件.lib是什么,以及lib.EXE的扩展功能

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

您的问题表明lib2链接到lib1中。我假设这意味着您将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会将LIB命令中指定的最后一个对象放入输出库

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


看来你已经想出了一些解决办法,但希望你现在能理解你所看到的行为。

< P>我刚刚在微软Visual C++ 2010 Express中提出了一个解决方案,它包含两个静态库项目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)" (??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 ========== 替换Debug\MyClass.obj的消息说明了这个问题。此消息是由Microsoft的Library Manager LIB.EXE在生成lib2.LIB时发出的。为了理解此消息,必须准确了解静态库文件.lib是什么,以及lib.EXE的扩展功能

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

您的问题表明lib2链接到lib1中。我假设这意味着您将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会将LIB命令中指定的最后一个对象放入输出库

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


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

EDIT:链接器没有在LIB1.lib中搜索LIB1:MyClass的定义,而是尝试在lib2的MyClass.obj中找到它们……对不起,忘了这一点,这没有任何意义:链接器没有在LIB1.lib中搜索LIB1:MyClass的定义,而是试图在lib2的MyClass.obj中找到它们……对不起,忘了这一点,这对于揭示链接没有任何意义。禁用LIB.exe的/NOLOGO选项后,我可以看到打包到LIB中的对象文件被其相对路径引用。对于MyClass示例,命令行输出类似于:Debug/MyClass.obj被Debug/MyClass.obj替换,因此整个问题的解决方案就是将lib1的对象文件保存到与lib2不同的位置。DebugLib1/*.obj,DebugLib2/*.obj然后lib1的对象可以链接到lib2,而不会在具有相同文件名的情况下碰撞对象名。非常欢迎。我很高兴我的回答帮助您找到了一个更理想的解决方案。感谢您为链接提供帮助。禁用LIB.exe的/NOLOGO选项后,我可以看到打包到LIB中的对象文件被其相对路径引用。对于MyClass示例,命令行输出类似于:Debug/MyClass.obj被Debug/MyClass.obj替换,因此整个问题的解决方案就是将lib1的对象文件保存到与lib2不同的位置。DebugLib1/*.obj,DebugLib2/*.obj然后lib1的对象可以链接到lib2,而不会在具有相同文件名的情况下碰撞对象名。非常欢迎。我很高兴我的回答帮助你找到了一个更理想的解决问题的办法。