程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 基於C++全局變量的聲明與界說的詳解

基於C++全局變量的聲明與界說的詳解

編輯:關於C++

基於C++全局變量的聲明與界說的詳解。本站提示廣大學習愛好者:(基於C++全局變量的聲明與界說的詳解)文章只能為提供參考,不一定能成為您想要的結果。以下是基於C++全局變量的聲明與界說的詳解正文


(1)編譯單位(模塊)
在VC或VS上編寫完代碼,點擊編譯按鈕預備生成exe文件時,編譯器做了兩步任務:
第一步,將每一個.cpp(.c)和響應的.h文件編譯成obj文件;
第二步,將工程中一切的obj文件停止LINK,生成終究.exe文件。
那末,毛病能夠在兩個處所發生:
一個,編譯時的毛病,這個重要是語法毛病;
一個,鏈接時的毛病,重要是反復界說變量等。
編譯單位指在編譯階段生成的每一個obj文件。
一個obj文件就是一個編譯單位。
一個.cpp(.c)和它響應的.h文件配合構成了一個編譯單位。
一個工程由許多編譯單位構成,每一個obj文件裡包括了變量存儲的絕對地址等。
(2)聲明與界說
函數或變量在聲明時,並沒有給它現實的物理內存空間,它有時刻可包管你的法式編譯經由過程;
函數或變量在界說時,它就在內存中有了現實的物理空間。

假如你在編譯單位中援用的內部變量沒有在全部工程中任何一個處所界說的話,那末即便它在編譯時可以經由過程,在銜接時也會報錯,由於法式在內存中找不到這個變量。
函數或變量可以聲明屢次,但界說只能有一次。
(3) extern感化
感化一:當它與"C"一路連用時,如extern "C" void fun(int a, int b);,則編譯器在編譯fun這個函數名時按C的規矩去翻譯響應的函數名而不是C++的。
感化二:當它不與"C"在一路潤飾變量或函數時,如在頭文件中,extern int g_nNum;,它的感化就是聲明函數或變量的感化規模的症結字,其聲明的函數和變量可以在本編譯單位或其他編譯單位中應用。
即B編譯單位要援用A編譯單位中界說的全局變量或函數時,B編譯單位只需包括A編譯單位的頭文件便可,在編譯階段,B編譯單位固然找不到該函數或變量,但它不會報錯,它會在鏈接時從A編譯單位生成的目的代碼中找到此函數。
(4)全局變量(extern)
有兩個類都須要應用配合的變量,我們將這些變量界說為全局變量。好比,res.h和res.cpp分離來聲明和界說全局變量,類ProducerThread和ConsumerThread來應用全局變量。(以下是QT工程代碼)

/**********res.h聲明全局變量************/ 
#pragma once 

#include <QSemaphore> 

const int g_nDataSize = 1000; // 臨盆者臨盆的總數據量 
const int g_nBufferSize = 500; // 環形緩沖區的年夜小 

extern char g_szBuffer[]; // 環形緩沖區 
extern QSemaphore g_qsemFreeBytes; // 掌握環形緩沖區的余暇區(指臨盆者還沒填湊數據的區域,或許花費者曾經讀取過的區域) 
extern QSemaphore g_qsemUsedBytes; // 掌握環形緩沖區中的應用區(指臨盆者已填湊數據,但花費者沒有讀取的區域) 
/**************************/ 

上述代碼中g_nDataSize、g_nBufferSize為全局常量,其他為全局變量。

/**********res.cpp界說全局變量************/ 
#pragma once 
#include "res.h" 

// 界說全局變量 
char g_szBuffer[g_nBufferSize]; 
QSemaphore g_qsemFreeBytes(g_nBufferSize); 
QSemaphore g_qsemUsedBytes; 
/**************************/ 

在其他編譯單位中應用全局變量時只需包括其地點頭文件便可。

/**********類ConsumerThread應用全局變量************/ 
#include "consumerthread.h" 
#include "res.h" 
#include <QDebug> 
ConsumerThread::ConsumerThread(QObject* parent) 
: QThread(parent) { 

ConsumerThread::ConsumerThread() { 


ConsumerThread::~ConsumerThread() { 

void ConsumerThread::run() { 
 for (int i = 0; i < g_nDataSize; i++) { 
  g_qsemUsedBytes.acquire();
  qDebug()<<"Consumer "<<g_szBuffer[i % g_nBufferSize]; 
  g_szBuffer[i % g_nBufferSize] = ' '; 
  g_qsemFreeBytes.release(); 
 } 
 qDebug()<<"&&Consumer Over"; 

/**************************/ 

也能夠把全局變量的聲明和界說放在一路,如許可以避免忘卻了界說,如下面的extern char g_szBuffer[g_nBufferSize]; 然後把援用它的文件中的#include "res.h"換成extern char g_szBuffer[];。
然則如許做很欠好,由於你沒法應用#include "res.h"(應用它,若到達兩次及以上,就湧現重界說毛病;注:即便在res.h中加#pragma once,或#ifndef也會湧現反復界說,由於每一個編譯單位是零丁的,都邑對它各行其是界說),那末res.h聲明的其他函數或變量,你也就沒法應用了,除非也都用extern潤飾,如許太費事,所以照樣推舉應用.h中聲明,.cpp中界說的做法。
(5)靜態全局變量(static)
留意應用static潤飾變量,就不克不及應用extern來潤飾,即static和extern弗成同時湧現。
static潤飾的全局變量的聲明與界說同時停止,即當你在頭文件中應用static聲清楚明了全局變量,同時它也被界說了。
static潤飾的全局變量的感化域只能是自己的編譯單位。在其他編譯單位應用它時,只是簡略的把其值復制給了其他編譯單位,其他編譯單位會別的開個內存保留它,在其他編譯單位對它的修正其實不影響自己在界說時的值。即在其他編譯單位A應用它時,它地點的物理地址,和其他編譯單位B應用它時,它地點的物理地址紛歧樣,A和B對它所做的修正都不克不及傳遞給對方。
多個處所援用靜態全局變量地點的頭文件,不會湧現重界說毛病,由於在每一個編譯單位都對它開拓了額定的空間停止存儲。
以下是Windows掌握台運用法式代碼示例:

/***********res.h**********/ 
static char g_szBuffer[6] = "12345"; 
void fun(); 
/************************/ 


/***********res.cpp**********/ 
#include "res.h" 
#include <iostream> 
using namespace std; 

void fun() { 
 for (int i = 0; i < 6; i++) { 
  g_szBuffer[i] = 'A' + i; 
 } 
 cout<<g_szBuffer<<endl; 

/************************/ 


/***********test1.h**********/ 
void fun1(); 
/************************/ 


/***********test1.cpp**********/ 
#include "test1.h" 
#include "res.h" 
#include <iostream> 
using namespace std; 

void fun1() { 
fun(); 

 for (int i = 0; i < 6; i++) { 
  g_szBuffer[i] = 'a' + i; 
 } 
 cout<<g_szBuffer<<endl; 

/************************/ 


/***********test2.h**********/ 
void fun2(); 
/************************/ 


/***********test2.cpp**********/ 
#include "test2.h" 
#include "res.h" 
#include <iostream> 
using namespace std; 

void fun2() { 
 cout<<g_szBuffer<<endl; 

/************************/ 


/***********main.cpp**********/ 
#include "test1.h" 
#include "test2.h" 

int main() { 
 fun1(); 
 fun2(); 

 system("PAUSE"); 
 return 0; 

/************************/ 

運轉成果以下:


按我們的直不雅印象,以為fun1()和fun2()輸入的成果都為abcdef,可現實上fun2()輸入切實其實是初始值。然後我們再跟蹤調試,發明res、test1、test2中g_szBuffer的地址都紛歧樣,分離為0x0041a020、0x0041a084、0x0041a040,這就說明了為何紛歧樣。
注:普通界說static 全局變量時,都把它放在.cpp文件中而不是.h文件中,如許就不會給其他編譯單位形成不用要的信息淨化。
(6)全局常量(const)
const零丁應用時,其特征與static一樣(每一個編譯單位中地址都紛歧樣,不外由於是常量,也不克不及修正,所以就沒有多年夜關系)。
const與extern一路應用時,其特征與extern一樣。
[code]
extern const char g_szBuffer[];      //寫入 .h中 
const char g_szBuffer[] = "123456"; // 寫入.cpp中 
[/code
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved