Классы с одинаковыми именами файлов в разных наследованиях библиотек - PullRequest
2 голосов
/ 03 февраля 2012

При наследовании от класса с тем же именем файла, который находится в другой библиотеке, компоновщик выдает неразрешенную внешнюю ошибку символа.Подумайте об этом наследовании: 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, включая как библиотеки libs, так и исполняемый файл, и с установленным VSвсе зависимости lib через Project Properties-> Common Properties-> Framework и References (вместо указания путей к библиотекам в настройках компоновщика) соединение успешно.

1 Ответ

0 голосов
/ 06 февраля 2012

Я только что принял решение в 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, как показано на этом снимке экрана:

enter image description here

Чтобы точно понять, что делает добавление файла .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.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...