[英]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;
這樣,就有一個明確定義的位置來存放a
和b
,並且編譯器可以正確連接點。
Collin已經描述了問題和解決方案,但我想強調一下這種樣式有多糟糕。
您甚至從這個簡單的練習中就發現,以這種方式使用全局變量通常是一件壞事。 除了已經發現的編譯器問題之外,使用全局變量在函數之間共享狀態還會導致以下問題:
它使該函數本身更難在其他程序中重用,因為該函數期望這些符號的存在。
對一個功能的更改可能會導致共享該狀態的其他功能出現問題(即更改未本地化至該功能);
代碼變得更難調試,因為任何人都可以隨時修改a
和b
。
理想情況下 ,函數應僅通過參數,返回值和異常(如果適用)進行通信; 在某些情況下,共享狀態是正確的答案,但這種情況相對較少且相差甚遠。
由於您顯然使用的是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;
}
由於x
和y
被聲明為引用類型(使用&
),因此在double_vars
寫入表達式 x
和y
等同於在main
寫入a
和b
。
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
寫入a
和b
相同。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.