Несколько определений одной и той же функции в C ++

Когда я использую git rebase? Почти никогда, потому что он переписывает историю. git merge - почти всегда предпочтительный выбор, потому что он уважает то, что на самом деле произошло в вашем проекте.

0
задан Christophe 2 March 2019 в 07:25
поделиться

2 ответа

Вы должны написать код random_double() в файле .cpp, отличном от файла .hpp или .h. Или добавьте inline перед double random_double() { //some code }, если вы храните свой код в своем файле .hpp.

0
ответ дан Scab 2 March 2019 в 07:25
поделиться

Проблема

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

Включающие охранники следят за тем, чтобы одно и то же определение не встречалось несколько раз в одном и том же модуле компиляции (например, если вы включили function.hpp в neuron.hpp и также включили его напрямую). Но здесь этот заголовок прямо или косвенно включен в main.cpp, ffnet.cpp и neuron.cpp, что дает первое определение и 2 недопустимых переопределения.

Решение

Необходимо изменить function.hpp, чтобы оставить только объявление функции:

#ifndef FUNCTIONS_HPP
#define FUNCTIONS_HPP
double random_double();  // no body !!
#endif

и переместить тела функций в отдельный function.cpp, который должен быть добавленным к вашей команде компилятора.

Преимущество этого подхода:

  • Затем можно скомпилировать функции полезности отдельно. Каждый раз, когда вы меняете тело функции, вам больше не нужно перекомпилировать весь cpp.
  • Инкапсуляция улучшена за счет совместного использования в hpp только того, что нужно знать другим модулям, и сокрытия деталей реализации.
  • Повторное использование может быть облегчено во всех проектах путем создания библиотеки функций.
  • Включения будут короче (в случае, если в некотором отдаленном будущем ваш код превратится в большой проект с тысячами hpp, это может заставить вас выиграть некоторое время)

Дополнительные замечания

Не уверен, что это применимо, но имейте в виду, что не стоит включать заголовок в пространство имен.

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

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

0
ответ дан Christophe 2 March 2019 в 07:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: