Ответ 1
Вот очень упрощенный, но, надеюсь, релевантный взгляд на то, что происходит, когда вы создаете свой код на С++.
С++ разбивает нагрузку исполняемого кода генерирующей машины на следующие разные фазы -
-
Предварительная обработка. Здесь будут использоваться все макросы -
#defines
и т.д., которые вы можете использовать. -
Компиляция. Каждый файл cpp вместе со всеми файлами
#include
d в этом файле, прямо или косвенно (вместе называемый модулем компиляции), преобразуется в машиночитаемый объектный код.Здесь С++ также проверяет, что все функции определены (т.е. содержат тело в
{
}
, например,void Foo( int x){ return Boo(x); })
справедливо ссылаются на другие функции.Как это делается, настаивая на том, что вы предоставляете хотя бы объявление этих других функций (например,
void Boo(int);
), прежде чем вы его вызываете, чтобы он мог проверить, что вы правильно его называете. Это можно сделать либо непосредственно в файле cpp, где он вызывается, либо обычно во включенном заголовочном файле.Обратите внимание, что только машинный код, соответствующий функциям, определенным в этом файле cpp и включенным, создается как двоичная версия этой единицы компиляции (например, Foo), а не те, которые просто объявлены (например, Boo).
-
Связывание - это этап, на котором С++ отправляется на охоту за объявленными и вызываемыми в каждом компиляторе элементами и связывает их с местами, где он вызван. Теперь, если не было определения, найденного в этой функции, компоновщик отказывается и ошибки. Точно так же, если он находит несколько определений одной и той же сигнатуры функции (по сути, имя и типы параметров, которые она принимает), она также выдает ошибку, поскольку она считает ее неоднозначной и не хочет выбирать один произвольно.
Последнее - это то, что происходит в вашем случае. Делая #include
файла fun.cpp
, оба fun.cpp
и mainfile.cpp
имеют определение funct()
, и компоновщик не знает, какой из них использовать в вашей программе, и жалуется на это.
Исправление, упомянутое выше, заключается в том, чтобы не включать файл cpp с определением funct()
в mainfile.cpp
и вместо этого переместить объявление funct()
в отдельный файл заголовка и включить его в mainline.cpp
. Таким образом, компилятор получит объявление funct()
, и компоновщик получит только одно определение funct()
от fun.cpp
и будет использовать его с уверенностью.