C++ 函数的多个定义,即使是在include保护中定义的
假设我有一个头文件C++ 函数的多个定义,即使是在include保护中定义的,c++,C++,假设我有一个头文件myheader.h,定义如下: #ifndef MY_HEADER #define MY_HEADER int MyFunction(int x) { return x + 1; } #endif 然后,我有两个源文件,它们都#包括这个头文件。这给了我一个编译错误: multiple definitions of 'MyFunction(int)' 为什么我的头文件中的include-guard不能阻止它被定义两次呢?链接器将为包含头文件的每个编译单元传递一个
myheader.h
,定义如下:
#ifndef MY_HEADER
#define MY_HEADER
int MyFunction(int x)
{
return x + 1;
}
#endif
然后,我有两个源文件,它们都#包括这个头文件。这给了我一个编译错误:
multiple definitions of 'MyFunction(int)'
为什么我的头文件中的include-guard不能阻止它被定义两次呢?链接器将为包含头文件的每个编译单元传递一个定义
链接器始终只需要1个定义
考虑只在一个源文件中定义函数,或者使用内联
指令。您需要标记函数内联
,如下所示:
#ifndef MY_HEADER
#define MY_HEADER
inline int MyFunction(int x)
{
return x + 1;
}
#endif
说明:
每次在任何.cpp文件中包含.h时,都会得到函数的定义。链接器不喜欢多个定义。然而,若您将函数标记为inline
,那个么您是在告诉编译器确保链接器会满意
如何使链接器快乐的真正方法取决于编译器和链接器,但实际上,它归结为两种策略:
- 内联函数-这意味着函数定义实际上从生成的代码中删除。相反,无论函数应该做什么,都会在调用函数的地方进行
- 将函数标记为本地名-链接器知道本地名是特定于特定文件的,并且将始终保持它们的独立性
声明(.h)不同于定义(.c、.cpp…)
一个好的做法是在头文件中声明一个函数,在guard内部:
//file foo.h: can be included in other header or implementation files
#ifndef MY_HEADER
#define MY_HEADER
int MyFunction(int x);
#endif
以及在实现文件中定义函数:
//file foo.c: not included in other files.
#include "foo.h" // to assert function declaration and definition match
int MyFunction(int x)
{
return x+1;
}
如果这两个源文件是链接的,那么它们都会将定义编译到其中(因为定义在标题中)。将声明保留在标题中,但将定义移动到单独的源文件中。include guard只能防止在一个翻译单元(一个源文件)中多次包含。这方面没有什么好的做法。有时这是一种合适的方法,有时则不然。