我正在将编写为一个芯片编写的代码移动到另一个芯片上。
出现的一个问题是多种多重定义错误。其中一些看起来是由于第一个芯片的链接器让我懒得在多个源文件中使用时声明变量extern。我以前根本没有使用extern(在something.h中声明和定义一个变量,在something.cpp和其他包含something.h的源文件中使用它)并且它编译和链接非常好。
我已经很好地解决了这些问题,我相信:现在我共享的变量有这样的模式:
Something.h
extern int foo;
Something.cpp
int foo = 0;
//using foo to do stuff
Main.cpp的
#include "Something.h"
//using foo to do stuff
都好。
这是我不理解的一点,似乎无法在这里或谷歌找到任何答案。我注意到同样的多重定义错误是由在Something.h中声明和定义的变量引起的,仅在Something.cpp中使用。
Something.h有一个包含守卫,所以我认为这不是因为Something.h被多次包含在我的程序中。
如果我将它声明为extern并在cpp文件中定义它,则错误消失,但这对我来说是错误的。我相信extern不需要在Something.h和Something.cpp之间链接变量。
任何建议都会非常感激,我真的很想了解我在这里缺少什么。
(顺便说一下,我正在使用Arduino IDE为ESP32编译。)
如果在头文件中声明变量:
#ifndef GLOBAL_H
#define GLOBAL_H
int foo = 0;
#endif
在头文件或翻译单元的每个包含中,都会创建一个新的整数实例。正如您所提到的,为了避免这种情况,您需要在头文件中将该项声明为“extern”并在实现文件中初始化它:
// .h
extern int foo;
// .cpp
int foo = 0
更多C ++方法可以是这样的:
#ifndef GLOBAL_H
#define GLOBAL_H
struct Global {
static int foo;
};
#endif
在你的cpp文件中:
#include "variables.h"
int Global::foo = 0;
C ++ 17使用内联变量修复此问题,因此您可以执行以下操作:
#ifndef GLOBAL_H
#define GLOBAL_H
inline int foo = 0;
#endif
有关更多信息,请参阅How do inline variables work?。
如果我将其声明为extern并在cpp文件中定义它,则错误消失,
问题是,即使包含保护等,变量也会在每个编译单元中创建一次 - 但由于它是全局的,因此它指向同一个变量。
要解决这个问题,您需要在anon中创建它。命名空间
Something.h
namespace {
int foo = 0;
}
或者,使用static关键字
Something.h
static int foo = 0;
两者都将在每个编译单元中创建一个不同的变量。