Функция уже определила ошибку в C ++ - PullRequest
13 голосов
/ 06 августа 2011

У меня есть файл с именем «SimpleFunctions.h», определенный следующим образом:

#ifndef SIMPLEFUNCTIONS_H
#define SIMPLEFUNCTIONS_H

namespace my_namespace {

double round(double r) { return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5); }
float round(float r) { return round((double)r); }

}

#endif // SIMPLEFUNCTIONS_H

Этот файл ранее был включен только в один файл, и он работал нормально.

Теперь я сегоднявключили его во второй файл, и он больше не работает.Во время ссылки он говорит мне, что функция уже определена в "firstfile.obj".

Однако, поскольку я использую include guard, я ожидал бы, что функции будут определены только один раз, или я пропустилчто-то?

Ответы [ 3 ]

25 голосов
/ 06 августа 2011

По умолчанию эти функции имеют внешнюю связь.Это означает, что каждая единица перевода имеет функции, называемые double round (double r) и float round (float r), что вызывает конфликт имен во время соединения.

Некоторые возможные решения:

  1. Объявите функции как статические, что подразумевает внутреннюю связь
  2. Встроенные функции
  3. Переместите реализацию из заголовка в файл ac / c ++

Подробнеездесь: Что такое внешняя связь и внутренняя связь?

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

4 голосов
/ 06 августа 2011

use 'inline'

inline double round(double r) { return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5); }
inline float round(float r) { return round((double)r); }

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

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

1 голос
/ 06 августа 2011

Лучший способ решить проблему - через шаблоны.Ваш код будет хорошо скомпилирован, если вы сделаете что-то вроде:

template <class T>
T round (T r) {
    return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5);
}

Ваш компоновщик перестанет жаловаться, и у вас будет одна функция для всех ваших нужд.

Это решение может быть улучшено с помощью черт типа.См. boost :: is_floating_point и boost :: enable_if

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