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

时间:2019-03-19 09:59:54

标签: c++ linker extern

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

出现的一个问题是多个多重定义错误。其中一些似乎是由于第一个芯片的链接器所致,让我懒于在多个源文件中使用变量时将变量声明为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

一切都很好。

这是我不了解的地方,似乎无法在此处或Google上找到任何答案。我注意到由在Something.h中声明和定义并在Something.cpp中仅使用 的变量引起的相同的多定义错误。

Something.h有一个include防护,所以我不认为这是由于Something.h在程序的某个位置多次被包含。

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

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

(顺便说一下,我正在使用Arduino IDE编译ESP32。)

3 个答案:

答案 0 :(得分:3)

  

如果我将其声明为extern并在cpp中对其进行定义,该错误就会消失   文件,

问题在于,即使在包含保护对象等情况下,该变量也会在每个编译单元中创建一次-但由于它是全局变量,因此指向相同的变量。

要解决此问题,您需要在一个时间里创建它。命名空间

Something.h

namespace {
  int foo = 0;
}

或者,使用static关键字

Something.h

 static int foo = 0;

两者都会在每个编译单元中创建一个不同的变量。

答案 1 :(得分:2)

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

#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?

答案 2 :(得分:0)

在 C++ 17 中,您可以通过内联变量解决此问题。内联变量避免了头文件中定义的变量的重复。头文件中定义的变量将被视为在 cpp 文件中初始化。它们不会被复制。所以可以直接包含代码。

相关问题