Классы с одинаковым именем файла в разных библиотеках проблема наследования

При наследовании от класса с тем же именем файла, который находится в другой библиотеке, компоновщик выдает неразрешенную ошибку внешнего символа. Подумайте об этом наследовании: 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.

lib2 ссылки в lib1

Затем какой-то исполняемый файл пытается связать lib2 и использовать производный MyClass, например

#include "\lib2\MyClass.h"

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

Не удается установить связь с

ошибка LNK2001: неразрешенный внешний символ "public: __thiscall LIB1 :: MyClass :: ~ MyClass (void)"

(то же самое для ctor)

Когда я просто меняю имя файла одного из MyClass.cpp на MyClass1.cpp, все в порядке.

Я подозреваю, что вместо поиска определений LIB1: MyClass в lib1.lib компоновщик пытается найти их в MyClass.obj (из lib2).

Такое поведение кажется слишком странным, чтобы быть умышленным. Что мне не хватает?

Кроме того, при настройке решения в VS2005 / 2010, включая как библиотеки, так и исполняемый файл, и наличие VS настраивает все зависимости библиотек через Project Properties-> Common Properties-> Framework and References (вместо предоставления путей к библиотекам в настройках компоновщика) соединение выполнено успешно.


person Tim Handschack    schedule 03.02.2012    source источник
comment
РЕДАКТИРОВАТЬ: вместо поиска определений для LIB1: MyClass в lib1.lib компоновщик пытается найти их в MyClass.obj (из lib2), я подозреваю ... извините, забудьте об этом, это не имеет никакого смысла   -  person Tim Handschack    schedule 03.02.2012


Ответы (1)


Я только что сделал решение в Microsoft 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 (LIB.EXE) при сборке lib2.lib. Чтобы понять это сообщение, важно точно понимать, что такое файл статической библиотеки (.lib), и, по расширению, что именно делает LIB.EXE.

Перво-наперво: при создании статической библиотеки код фактически не связывается. Файл .lib - это просто архив, содержащий внутри один или несколько файлов .obj. Другими словами, цель файла .lib - предоставить удобный способ распространения коллекции файлов .obj как одного файла. Все, что делает LIB.EXE, - это упаковывает файлы .obj проекта в файл .lib. LIB.EXE также имеет параметры для других действий с файлами .lib, таких как перечисление всех содержащихся файлов .obj и их извлечение; см. MSDN для получения дополнительной информации.

В вашем вопросе указано, что "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, который содержит все файлы .obj в lib1.lib, а также MyClass.obj. Тот факт, что lib1.lib также содержит объект с именем MyClass.obj, является источником вашей проблемы. Как указано в документации LIB.EXE в MSDN:

Чтобы заменить член библиотеки новым объектом, укажите библиотеку, содержащую заменяемый элемент, и имя файла для нового объекта (или библиотеки, которая его содержит). Когда объект с таким же именем существует более чем в одном входном файле, LIB помещает последний объект, указанный в команде LIB, в выходную библиотеку.

Сообщение «Замена Debug \ MyClass.obj» выводится на консоль, когда LIB.EXE видит второй экземпляр MyClass.obj, поскольку считает, что второй MyClass.obj должен заменить первый. Переименование одного из файлов MyClass.cpp в MyClass1.cpp устраняет эту проблему, поскольку больше не существует двух объектных файлов с именем MyClass.obj, поэтому они оба могут счастливо жить вместе в одном файле .lib.

Похоже, вы уже нашли обходные пути для этого, но, надеюсь, теперь вы понимаете поведение, которое наблюдаете.

person chess007    schedule 06.02.2012
comment
Спасибо, что пролили свет на ссылку. После отключения параметра / NOLOGO в LIB.exe я мог видеть, что на объектные файлы, упакованные в библиотеку, ссылались по их относительному пути. Для примера MyClass вывод командной строки был примерно таким: Debug / MyClass.obj заменен на Debug / MyClass.obj. Таким образом, решение всего этого состоит в том, чтобы просто сохранить объектные файлы lib1 в другое расположение, чем у lib2. (DebugLib1 / *. Obj, DebugLib2 / *. Obj) Затем объекты lib1 могут быть связаны с lib2, не сталкиваясь с именами объектов, имея одинаковые имена файлов. - person Tim Handschack; 06.02.2012
comment
Пожалуйста. Я рад, что мой ответ помог вам найти более желательное решение вашей проблемы. - person chess007; 07.02.2012