QГрабля#5
При инстанцировании шаблонов внутри классов, использующих мета-объектную систему Qt, а также в ряде других ситуаций при использовании этой библиотеки (на практике особенно часто - при создании Unit-тестов силами QTestLib) возможно возникновение ошибки линковки multiple definition. Связано это с тем, что moc парсит заголовочные файлы и для всех файлов, содержащих класс с макросом Q_OBJECT генерирует *.cpp-файл с необходимым для функционирования мета-объектной системы Qt кодом. Такой файл становится отдельной единицей компиляции, и если в нем, как пример, инстанцируется какой-либо шаблон, то он, согласно правилам компиляции шаблонов C++, полностью включается в генерируемый объектный файл. Врочем, ровно то же происходит при инстанцировании такого шаблона в любом другом *.cpp файле, например, содержащем main(). В итоге в ходе линковки один и тот же шаблон обнаруживается сразу в нескольких объектных файлах, что и приводит к возникновению описанной выше ошибки.
Поправить ситуацию можно несколькими способами. Можно все методы шаблона сделать
inline-овыми (см. описание похожей ситуации), можно модифицировать сборку Qt-проекта вручную так, чтобы генерируемый moc'ом файл просто включался в файл, по которому он был сгенерирован (именно это в простых случаях автоматизировано выполняет этот скрипт (см. замечания)) Либо можно позволить линковщику самостоятельно разрешать такие конфликты, просто выбирая первое из многочисленных определений (ключ -z muldefs для *nix-линковщика ld) Интегрировать нужные ключи можно автоматически в Makefile с помощью этого скрипта (см. описание), либо просто ключив в *.pro-файл строку вида:
При инстанцировании шаблонов внутри классов, использующих мета-объектную систему Qt, а также в ряде других ситуаций при использовании этой библиотеки (на практике особенно часто - при создании Unit-тестов силами QTestLib) возможно возникновение ошибки линковки multiple definition. Связано это с тем, что moc парсит заголовочные файлы и для всех файлов, содержащих класс с макросом Q_OBJECT генерирует *.cpp-файл с необходимым для функционирования мета-объектной системы Qt кодом. Такой файл становится отдельной единицей компиляции, и если в нем, как пример, инстанцируется какой-либо шаблон, то он, согласно правилам компиляции шаблонов C++, полностью включается в генерируемый объектный файл. Врочем, ровно то же происходит при инстанцировании такого шаблона в любом другом *.cpp файле, например, содержащем main(). В итоге в ходе линковки один и тот же шаблон обнаруживается сразу в нескольких объектных файлах, что и приводит к возникновению описанной выше ошибки.
Поправить ситуацию можно несколькими способами. Можно все методы шаблона сделать
inline-овыми (см. описание похожей ситуации), можно модифицировать сборку Qt-проекта вручную так, чтобы генерируемый moc'ом файл просто включался в файл, по которому он был сгенерирован (именно это в простых случаях автоматизировано выполняет этот скрипт (см. замечания)) Либо можно позволить линковщику самостоятельно разрешать такие конфликты, просто выбирая первое из многочисленных определений (ключ -z muldefs для *nix-линковщика ld) Интегрировать нужные ключи можно автоматически в Makefile с помощью этого скрипта (см. описание), либо просто ключив в *.pro-файл строку вида:
QMAKE_LFLAGS += -z muldefs
Комментариев нет:
Отправить комментарий