Если B.cpp и C.c включают хиджры, то оба компилируется с определением из M
, так как объектные файлы будут содержать код для M
. Когда компоновщик собирает все функции, он видит, что M
определен в двух объектных файлах и не знает, какой из них использовать. Таким образом, компоновщик поднимает LNK2005.
Если поместить функцию M
в класс декларации, то знаки компилятора/ручки M
в качестве встроенной функции. Эта информация записывается в файл объекта. Линкер видит, что оба объектных файла содержат определение для inline версии CA::M
, поэтому он предполагает, что оба они равны и случайно выбирают одно из двух определений.
Если бы вы написали
class CA {
public:
int M();
};
int CA::M()
{
return 1;
}
это вызвало бы те же проблемы (LNK2005) в качестве начальной версии, потому что тогда CA::M
не был бы рядный больше.
Как вы уже догадались, для вас есть два решения. Если вы хотите M
быть встраиваемыми, а затем изменить код
__inline int M()
{
return 1;
}
Если вы не заботитесь о встраивании, то, пожалуйста, это стандартный способ и поставить функцию декларацию в заголовочном файл:
extern int M();
и поставить функцию определение в файл CPP (для Ah это было бы в идеале быть a.cpp):
int M()
{
return 1;
}
Обратите внимание, что extern
не обязательно необходим в файле заголовка.
Другой пользователь предложил, чтобы писать
static int M()
{
return 1;
}
I'ld не рекомендуется. Это означало бы, что компилятор помещает M
в оба ваших объектных файла и отмечает M
как функцию, которая видна только в каждом объектном файле. Если компоновщик видит, что функция в B.cpp вызывает M
, она находит M
в B.obj и в C.obj. Оба имеют M
, обозначенные как статические, поэтому компоновщик игнорирует M
в C.obj и выбирает M
от B.obj. И наоборот, если функция в C.cpp вызывает M
, компоновщик выбирает M
из C.obj. Вы получите несколько определений M, все с той же реализацией. Это пустая трата пространства.
Вы не можете определить функцию в файлах заголовков, вы объявляете их в файлах заголовков. Однако классы могут быть объявлены в файлах заголовков. Все определения функций должны поступать в исходные файлы, за исключением нескольких строк. –