如何在多个文件中使用变量

How can I use variables in multiple files?

本文关键字:变量 文件      更新时间:2023-10-16

我想在标题中定义一个变量,并能够在多个文件中使用它。例如在某个地方定义了可变的a,并且能够在p1.cpp和p2.cpp

中使用/更改它

这是一个示例,其中有3个简单的文件,即我要做的事情。

// vars.hpp
#ifndef VARS_HPP
#define VARS_HPP
int a = 1;
float b = 2.2;
void double_vars();
#endif

// vars.cpp
#include "vars.hpp"
void double_vars () {
    a *= 2;
    b *= 2;
}
// vars_main.cpp
#include <cstdio>
#include "vars.hpp"
int main () {
    printf("a: %d; b: %fn", a, b);
    double_vars();
    printf("a: %d; b: %fn", a, b);
}

现在,用:

编译上述内容
g++ -Wall -W -g vars.cpp vars_main.cpp -o vars && ./vars

给我以下错误:

/tmp/ccTPXrSe.o:(.data+0x0): multiple definition of `a'
/tmp/ccnc1vof.o:(.data+0x0): first defined here
/tmp/ccTPXrSe.o:(.data+0x4): multiple definition of `b'
/tmp/ccnc1vof.o:(.data+0x4): first defined here

有人可以向我解释为什么会发生这种情况?我的标题文件中有警卫,据我所知,只有一旦就可以包括在内,因此不应有多个声明

在标题文件中,写下:

extern int a;
extern float b;

这将声明变量。

在一个CPP文件中,写下:

int a = 1;
float b = 2.2;

这将定义变量。只要变量被精确定义一次,您将定义放置在哪个CPP文件上都无关紧要。

首先,不要这样做。全球可变状态通常是一件坏事。

问题是,一旦链接器完成了包含措施中的文件的结合,它已经看到了两次,一次在main.cpp中,一次在vars_main.cpp中:

int a = 1;
float b = 2.2;

如果仅将其放入标题文件中,则会以多个翻译单元显示,一次用于包含标头的每个cpp文件。编译器不可能知道您在说哪个A和B。

解决此问题的方法是在标题中声明extern

extern int a;
extern float b;

这告诉编译器a和b是在某个地方定义的,不一定在代码的这一部分中。

然后,在您的一个CPP文件中,您将定义它们:

int a = 1;
float b = 2.2;

这样,ab的存储空间有一个定义明确的位置,并且编译器可以正确连接点。

collin已经描述了问题和解决方案,但我想强调这是多么糟糕的样式。

您即使是从这个简单的练习中发现的,以这种方式使用全球群体通常是一件坏事。除了您已经发现的编译器问题外,使用Globals在功能之间共享状态会导致以下问题:

  • 它使功能本身在其他程序中更难重复使用,因为该功能期望这些符号的存在;

  • 更改一个函数可能会在共享该状态的其他功能中引起问题(即,更改未本地化到函数);

  • 代码变得更难调试,因为任何人都可以随时修改ab

理想情况下,函数应仅通过参数,返回值和异常(如果适用)进行通信;有时共享状态是正确的答案,但是相对较少,而且相对较远。

由于您显然使用了C 编译器,因此我将使用引用而不是指示器来执行C 的方式。我还将使用C iostream例程,而不是cstdio(写C或C ;尝试混合两个只会导致胃灼热)。

vars.hpp:

#ifndef VARS_H  // Include guard to prevent multiple inclusion
#define VARS_H
void double_vars(int &, float &);
#endif

vars.cpp:

#include "vars.hpp"
void double_vars(int &x, float &y)
{
  x *= 2;    
  y *= 2.0;  
}

main.cpp:

#include <iostream>
#include "vars.hpp"
int main(void)
{
  int a = 1;
  float b = 2.2;
  std::cout << "a: " << a << "; b: " << b << std::endl;
  double_vars(a, b);
  std::cout << "a: " << a << "; b: " << b << std::endl;
  return 0;
}

由于xy被称为参考类型(使用&),因此在double_vars中写入 expressions expressions x and y等于 ab inmain

c的方法是指代而不是参考文献:

vars.h:

#ifndef VARS_H  // Include guard to prevent multiple inclusion
#define VARS_H
void double_vars(int *, float *); 
#endif

vars.c:

#include "vars.h"
void double_vars(int *x, float *y)
{
  *x *= 2;    
  *y *= 2.0;  
}

main.c:

#include <stdio.h>
#include "vars.h"
int main(void)
{
  int a = 1;
  float b = 2.2;
  printf("a: %d; b: %fn", a, b);
  double_vars(&a, &b);
  printf("a: %d; b: %fn", a, b);
  return 0;
}

在这种情况下,我们使用指针而不是引用,因此我们需要将表达式的结果传递给double_vars &a&b;在功能中,写入表达式*x*yamain中的b相同。