Подтвердить что ты не робот

С++: ошибка множественного определения для глобальных функций в файле заголовка

Эта функция является глобальной и определяется в файле заголовка (временно я хочу сохранить его там).

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

Исходный файл не содержит вхождения этой глобальной функции.

Любые подсказки о причине ошибки?

Я могу опубликовать код, если кому-то это интересно.

mainwindow.o: In function `tileForCoordinate(double, double, int)':
mainwindow.cpp:(.text+0x310): multiple definition of `tileForCoordinate(double, double, int)'
main.o:main.cpp:(.text+0xd0): first defined here
moc_mainwindow.o: In function `qHash(QPoint const&)':
moc_mainwindow.cpp:(.text+0x0): multiple definition of `qHash(QPoint const&)'
main.o:main.cpp:(.text+0x0): first defined here
moc_mainwindow.o: In function `tileForCoordinate(double, double, int)':
moc_mainwindow.cpp:(.text+0x150): multiple definition of `tileForCoordinate(double, double, int)'
main.o:main.cpp:(.text+0xd0): first defined here
collect2: ld returned 1 exit status
make: *** [SimpleRouting] Error 1
4b9b3361

Ответ 1

отметьте его как inline:

 inline void globalfunc() { 
 }

хотя это означает, что он больше не будет строго глобальным - вы получите копию в каждой единицы перевода, которая использует заголовок, но компоновщик не будет возражать против этого.

Ответ 2

Если вы поместите функцию в заголовок, она будет сгенерирована для каждого файла c/cpp, который включает этот заголовок, ведущий к дублированию. Создание встроенного модуля поможет.

Изменить, объяснение

Защитники заголовков, как #ifndef, #define... #endif конструкция часто вызывается только для предотвращения двойного и рекурсивного включения в один файл cpp. Это имеет значение в случае, когда исходный файл включает заголовки A и B и B также включает A. Рекурсивное включение произойдет, если A также включил B.

Ваша проблема возникает из-за того, что у вас есть несколько файлов .cpp. Во время компиляции одного cpp компилятор не знает о существовании других файлов cpp.

Обратите внимание, что #include, #ifdef и друзья - это препроцессорные директивы. Предварительная обработка происходит в исходных файлах перед компиляцией (считается, что это часто рассматривается и выполняется как часть процесса компиляции). Препроцессор в основном представляет собой текстовый процессор. Например, #include по тексту заменяется содержимым файла заголовка. Содержимое #ifdefs, которые оценивают значение false, удаляется из кода. Фактический компилятор получает один большой файл, состоящий из cpp и всех ссылочных файлов include, которые он переводит в объектный файл.

Ответ 3

У вас есть 2 варианта:

Отметьте его как встроенный, как объясняется nbt, или как static.

inline возьмет реализацию глобальной функции от источника и скопирует ее туда, где вызывается функция.

inline void global_func ()
{
...
}

static сообщит компоновщику, чтобы он не копировал код в новый объектный файл, а скорее ссылался только на оригинал.

static void global_func ()
{
...
}

Ответ 4

Для глобальной функции, определенной в заголовочном файле, объявить ее в неименованном пространстве имен должно/также работать. Согласно С++ Как программировать Deitel, в С++ неназванное пространство имен предпочтительнее статического.

Итак, вы можете сделать это:

// \file GlobalFunctions.h

namespace  // an un-named namespace
{

void GlobalFunctionOne() {...implementation...}

} // end un named namespace

Ответ 5

#ifndef SOMESTRING
#define SOMESTRING
... header code
#endif

Код заголовка будет включен только в первый раз.