Когда я использую git rebase
? Почти никогда, потому что он переписывает историю. git merge
- почти всегда предпочтительный выбор, потому что он уважает то, что на самом деле произошло в вашем проекте.
Вы должны написать код random_double()
в файле .cpp, отличном от файла .hpp или .h. Или добавьте inline
перед double random_double() { //some code }
, если вы храните свой код в своем файле .hpp.
У вас есть определение функции с полным кодом в заголовке, который вы включаете в несколько модулей компиляции. Это приводит к тому, что функция определяется в каждом модуле компиляции (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
, который должен быть добавленным к вашей команде компилятора.
Преимущество этого подхода:
Не уверен, что это применимо, но имейте в виду, что не стоит включать заголовок в пространство имен.
Я также рекомендую прочитать эту статью о заголовках . Это старый, но совет все еще очень актуален: -)
Обратите внимание, что существуют исключения из ODR для классов и встроенных функций, и в этом случае множественные определения должны быть точно такой же последовательностью токенов.