在头文件中声明和定义并仅在其 cpp 文件中使用的变量存在多重定义错误

JRV*_*ale 4 c++ linker extern

我正在将为一个芯片编译而编写的代码移动到另一芯片上。

出现的一个问题是存在大量的多重定义错误。其中一些似乎是由于第一个芯片的链接器让我在跨多个源文件使用变量时懒于声明变量 extern。我以前根本没有使用 extern (在 Something.h 中声明并定义一个变量,在 Something.cpp 和其他包含 Something.h 的源文件中使用它),并且它编译和链接得很好。

我相信我已经很好地解决了这些问题:现在我共享的变量具有以下模式:

某事.h

extern int foo;
Run Code Online (Sandbox Code Playgroud)

一些东西.cpp

int foo = 0;

//using foo to do stuff
Run Code Online (Sandbox Code Playgroud)

主要.cpp

#include "Something.h"

//using foo to do stuff
Run Code Online (Sandbox Code Playgroud)

都好。

这是我不明白的一点,似乎无法在这里或在谷歌上找到任何答案。我注意到相同的多重定义错误是由 Something.h 中声明和定义并在 Something.cpp 中使用的变量引起的。

Something.h 有一个包含保护,所以我不认为这是因为 Something.h 在我的程序中的某个地方被多次包含。

如果我将其声明为 extern 并在 cpp 文件中定义它,错误就会消失,但这对我来说是错误的。我相信不需要 extern 来链接 Something.h 和 Something.cpp 之间的变量。

任何建议将不胜感激,我真的很想了解我在这里缺少什么。

(顺便说一句,我正在使用 Arduino IDE 为 ESP32 进行编译。)

moh*_*uje 9

如果您在头文件中声明变量:

#ifndef GLOBAL_H
#define GLOBAL_H

int foo = 0;

#endif
Run Code Online (Sandbox Code Playgroud)

在头文件或翻译单元的每次包含中,都会创建整数的新实例。正如您所提到的,为了避免这种情况,您需要在头文件中将该项目声明为“extern”,并在实现文件中对其进行初始化:

// .h
extern int foo;

// .cpp
int foo = 0
Run Code Online (Sandbox Code Playgroud)

一种更 C++ 的方法可以是这样的:

#ifndef GLOBAL_H
#define GLOBAL_H

struct Global {
    static int foo;
};
#endif
Run Code Online (Sandbox Code Playgroud)

在你的 cpp 文件中:

#include "variables.h"

int Global::foo = 0;
Run Code Online (Sandbox Code Playgroud)

C++17 通过内联变量修复了这个问题,所以你可以这样做:

#ifndef GLOBAL_H
#define GLOBAL_H

inline int foo = 0;

#endif
Run Code Online (Sandbox Code Playgroud)

请参阅内联变量如何工作?了解更多信息。