У меня есть две реализации класса (.cpp files
)
Им обоим нужна функция, которая была реализована в header
(.h) файл. Оба файла .cpp включают в себя файл .h. После компиляции два .cpp
файлов становится два .o
файлы.
Функция должна быть определена дважды при связывании двух объектных файлов?
Можно #ifndef
предотвратить эту ситуацию?
я использовал #ifndef
но я получил следующее сообщение,
ld: 1 duplicate symbol for architecture x86_64
Вы должны понимать разницу между функцией декларация (утверждение, что функция с заданным именем и сигнатурой существует) и функция определение (код, который определяет, что на самом деле делает функция).
если ты определять функция в заголовке, затем функция будет определена в каждом объектном файле, и вы получите конфликт при попытке связать их вместе; #ifndef
не решит эту проблему.
Там не будет такой проблемы, если вы объявлять функция в заголовке, и определять это в исходном файле (который должен быть скомпилирован в объект и связан с объектами, которые его используют). В этом простом случае #ifndef
не нужен
Например, функция foo
может быть объявлено в foo.h
:
int foo(int);
и определяется в foo.cpp
:
int foo(int n)
{
return(n+3);
}
#ifndef
макрос решает другую проблему.
В качестве альтернативы ответу Беты вы можете определять бесплатная функция внутри заголовочного файла, которая будет включена в несколько блоков перевода, используя inline
ключевое слово. Учти это:
// Foo.h
int foo(){return 1;}
// UsesFoo1.cpp
#include "Foo.h"int usesFoo2(){return foo();}
// UsesFoo2.cpp
#include "Foo.h"int usesFoo1(){return foo();}
// Main.cpp
#include <iostream>
int usesFoo1();
int usesFoo2();
int main()
{
std::cout << usesFoo1() + usesFoo2() << std::endl;
}
Это приводит к ошибке компоновщика, потому что int foo()
определяется в двух отдельных единицах перевода. Однако при добавлении inline
ключевое слово здесь:
// Foo.h
inline int foo(){return 1;}
Примечание: функции, определенные внутри определений классов, неявно имеют inline
ключевое слово, так что вы можете опустить его там.