簡體   English   中英

如何在多個文件中使用變量?

[英]How can I use variables in multiple files?

我想在標頭中定義一個變量,並能夠在多個文件中使用它。 例如,在某處定義了變量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: %f\n", a, b);
    double_vars();
    printf("a: %d; b: %f\n", 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已經描述了問題和解決方案,但我想強調一下這種樣式有多糟糕。

您甚至從這個簡單的練習中就發現,以這種方式使用全局變量通常是一件壞事。 除了已經發現的編譯器問題之外,使用全局變量在函數之間共享狀態還會導致以下問題:

  • 它使該函數本身更難在其他程序中重用,因為該函數期望這些符號的存在。

  • 對一個功能的更改可能會導致共享該狀態的其他功能出現問題(即更改未本地化至該功能);

  • 代碼變得更難調試,因為任何人都可以隨時修改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寫入表達式 xy等同於在main寫入ab

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: %f\n", a, b);
  double_vars(&a, &b);
  printf("a: %d; b: %f\n", a, b);
  return 0;
}

在這種情況下,我們使用指針而不是引用,因此我們需要將表達式 &a&b的結果傳遞給double_vars 在函數中,寫入表達式*x*y與在main寫入ab相同。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM