理解C链接器错误:多重定义

Understanding C linker error: multiple definition

本文关键字:定义 错误 链接 理解      更新时间:2023-10-16

我有一个包含多个头文件和.cpp文件的项目。所有头文件都包含保护。

有一个名为Constants.h的文件,我在其中定义了一些常量。其中一些带有定义,一些是常量变量。

还有更多的头.cpp文件对,其中包含代码。其中一个确实包含类,其他的则不包含。

当我把我的文件包括到我的主文件(arduino草图)中时,我会得到很多链接器错误,声称有些变量有多个定义。

我读到,这主要发生在包含.c.cpp文件时,而我没有这样做。所有.cpp文件都只包含相应的头文件。

我确实设法找到了多个解决方案建议:

1)inline:

通过函数,inline可以用来解决这个问题。然而,对于变量来说,这是不可能的。

2)匿名namespace:

这是我使用的解决方案之一。我在所有有问题的定义周围放置了匿名名称空间。它确实起了作用,但我不明白为什么会起作用。有人能帮我理解吗?

3)将定义移动到.cpp文件中:

这是我有时使用的另一种方法,但这并不总是可能的,因为我需要在其他代码中使用我的一些定义,这些定义不属于这个头文件或它的代码(我承认这是糟糕的设计)。

有人能向我解释一下问题到底在哪里,以及为什么这些方法有效吗?

其中一些带有定义,一些作为常量变量。

在C中,const并不意味着与在C++中相同的东西。如果你有这个:

const int foo = 3;

在标头中,任何包含标头的C++转换单元都将有一个名为foo静态变量(命名空间范围中的const表示内部链接)。此外,foo甚至可以被许多C++构造认为是一个常数表达式。

C中的情况并非如此。foo是具有外部链接的文件范围内的对象。因此,您将有来自C翻译单元的多个定义。

一个快速的解决方案是将定义更改为这样的东西:

static const int foo = 3;

这在C++中是多余的,但在C.中是必需的

除了Story Teller的出色解释外,要定义全局变量,请使用以下内容:

// module.h
#include "glo.h"
// glo.h
#ifndef EXTERN
# define EXTERN extern
#endif
EXTERN int myvar;
// main.c
#define EXTERN
#include "glo.h"

main.c中,将声明所有变量(即为它们分配空间),在包括glo.h的所有其他c文件中,所有变量都是已知的。

不应该在头文件中声明任何对象,应该将其移动到c\c++文件中。

在标题中,您可以:

  • 声明类型,如:classes、structs、typedefs等
  • 提出函数(而不是类)的声明
  • 放入内联(或类中)函数(+body)
  • 您可以添加extern声明
  • 你可以把你的宏

static声明可能会多次声明内容,因此不建议这样做。