函数的多个定义,即使在包含保护中定义

Multiple definitions of a function even though defined inside an include guard

本文关键字:定义 包含 保护 函数      更新时间:2023-10-16

假设我有一个头文件myheader.h定义如下:

#ifndef MY_HEADER
#define MY_HEADER
int MyFunction(int x)
{
    return x + 1;
}
#endif

然后,我有两个源文件,它们都#include这个头文件。这给了我一个编译错误:

multiple definitions of 'MyFunction(int)'

为什么我的头文件中的包含保护不会阻止它被定义两次?

您需要

将函数标记为inline,如下所示:

#ifndef MY_HEADER
#define MY_HEADER
inline int MyFunction(int x)
{
    return x + 1;
}
#endif

解释

每次在任何.cpp文件中包含 .h 时,最终都会得到函数的定义。链接器不喜欢多个定义。但是,如果您将函数标记为inline,则告诉编译器确保链接器将得到满足。

如何使链接器满意的真正方法取决于编译器和链接器,但在实践中,它归结为两种策略:

  • 内联函数 - 这意味着函数定义实际上已从生成的代码中删除。相反,无论函数应该做什么,都将在调用函数的位置完成。
  • 将函数标记为本地名称 - 链接器知道本地名称特定于特定文件,并且将始终将它们分开。

链接器将为每个包含标头的编译单元传递一个定义。

链接器将始终需要正好 1 个定义。

请考虑在一个源文件中定义函数,或者使用 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;
}