C ++: ошибка множественного определения глобальных функций в заголовочном файле - PullRequest
18 голосов
/ 21 мая 2011

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

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

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

Есть ли какие-либо подсказки о причине ошибки?

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

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

Ответы [ 5 ]

29 голосов
/ 21 мая 2011

пометить как inline:

 inline void globalfunc() { 
 }

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

10 голосов
/ 21 мая 2011

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

Редактировать, объяснение

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

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

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

9 голосов
/ 07 ноября 2013

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

Пометьте его как встроенное, как указано в nbt, или как статическое.

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

inline void global_func ()
{
...
}

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

static void global_func ()
{
...
}
4 голосов
/ 19 декабря 2013

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

Так что вы можете сделать это:

// \file GlobalFunctions.h

namespace  // an un-named namespace
{

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

} // end un named namespace
0 голосов
/ 21 мая 2011
#ifndef SOMESTRING
#define SOMESTRING
... header code
#endif

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

...