gcc множественное определение … только выпуск

Я определил функцию в заголовочном файле. В отладке он компилируется и связывается нормально. В выпуске я получаю ошибку компиляции «множественное определение` blah :: blah (blah& бла) «» для каждого объектного файла каждого класса, который включает заголовок.

Я использую gcc-4.8.1. Я не могу опубликовать фактический код, в этой версии имена изменены, чтобы защитить невинных:

#ifndef INCLUDE_SMELLS_FUNNY
#define INCLUDE_SMELLS_FUNNY

#include "ParentClass.h"#include "ChildClassA.h"#include "ChildClassB.h"
namespace someplace {

bool smellsFunny(const ParentClass& someData) {

// All ChildClass As smell funny
if(dynamic_cast<const ChildClassA*>(&someData)) {
return true;
}

// If ChildClass B, need to check if smells funny
const ChildClassB* childB = dynamic_cast<const ChildClassB*>(&someData)
if(childB) {
return childB->MoreThanAWeekOld();
}

// Default is smells OK
return false;
}

}

#endif // INCLUDE_SMELLS_FUNNY

Я не смог найти какой флаг gcc ответственен.
Конечно, исправить это просто перенести реализацию в файл cpp. Но почему это необходимо? Почему это происходит только в релизе?

1

Решение

Я не могу сказать точно, но, возможно, в режиме отладки функция рассматривается как встроенная функция.

1

Другие решения

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

Есть несколько решений для этого:

  1. Отметить функцию как static, Это означает, что каждое определение в единицах перевода не будет экспортировано.
  2. Отметить функцию как inline, Это работает в основном так же, как первый вариант.
  3. Положить определение функции в исходном файле, и только его декларация в заголовочном файле.

Для небольшой функции, такой как у вас, альтернатива 2 может быть хорошей. Если у вас есть функция большего размера, которую нельзя легко встроить, вам следует использовать альтернативу 3.

Кроме того, если вы идете с номером 3, то вам не нужно включать файлы заголовков, а затем уменьшить риск циклического включения.

2

Поскольку вы поместили определение функции в заголовок, вам нужно пометить его inline:

inline bool smellsFunny(const ParentClass& someData) { ...

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

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

2

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

1
По вопросам рекламы [email protected]