C++中static和extern的微妙細節
static和extern在C和C++中可以用來既可以修飾資料(變數和常量),還可以修飾函式。
如果用來修飾變數常量資料識別符號,則static和extern的時間特性(儲存特性)相同的,都是靜態儲存,儲存在全域性資料區,但是static是在定義時生成,而extern則是在程式執行前已經建立(早於main()函式執行),一直到程式結束銷燬,但是static要早於extern,所以MFC採用全域性xxApp類物件中main()啟動程式,而Java語言採用靜態Main類物件中main()啟動程式都是可行的;而它們的空間特性(作用域)不同,static識別符號是通常指區域性資料(靜態全域性變數(常量)指是約束在內部變數(常量);靜態區域性變數和常量是塊作用域;類靜態資料成員則是類作用域,受類訪問約束符控制,但是被所有類物件共享;不同於普通類資料成員每個類物件都要建立其記憶體副本),而extern識別符號是全域性資料(全域性變數和常量,具有檔案作用域,通過包含其宣告檔案,可以被其它檔案訪問,不能用於類資料成員)。
如果用來修飾函式,則static函式和extern函式的時間特性(儲存特性)也是相同的,都是靜態儲存,也是程式執行時就已經存在記憶體;而其空間特性(作用域)不同,static指內部函式,侷限在檔案內部使用,而extern指外部函式,通過include標頭檔案(介面),可以被其它檔案使用。
實際使用要注意:static,extern通常加在變數、常量宣告和函式宣告前面,除非是定義和宣告合二為一的,才加在定義前;一般在函式外部定義的都預設為extern全域性的(變數、常量),普通函式也預設為extern(外部)的,因此要宣告為靜態變數、常量或者static內部函式必須顯式指定,而且static內部函式通常宣告在CPP檔案中,以達到隱藏介面,防止和其它同名外部函式名字衝突。例如:
gloab.h
#ifndef TEST_H_INCLUDED
#define TEST_H_INCLUDED
extern int Gloab_Int; //全部變數宣告
#endif // TEST_H_INCLUDED
gloab.cpp
#include "gloab.h"
int Gloab_Int = 1000;
print.h
#ifndef PRINT_H_INCLUDED
#define PRINT_H_INCLUDED
extern void print();
#endif // PRINT_H_INCLUDED
print.cpp
#include "print.h"
#include "test.h"
#include
static void printStatic(); //內部介面必須在cpp檔案中宣告,或者先定義在呼叫。
void print()
{
Gloab_Int += 1000;
std::cout << "Gloab_Int = " << Gloab_Int << std::endl;
printStatic();
}
int gInit = 10; //全域性變數沒有在標頭檔案宣告釋放介面,不能為外部檔案使用,而且外部檔案不能存在同名外部全域性變數
static int sgInit = 100; //靜態變數,表示其為內部變數,不能釋放宣告,為外部檔案使用;
//可以存在同名的外部全域性變數,只要不在本檔案中直接或間接包含其標頭檔案
void printStatic()
{
int iTemp = 0;
static int siVal = 1;
std::cout << "iTemp = " << iTemp++ << std::endl;
std::cout << "siVal = " << siVal++ << std::endl;
std::cout << "gInit = " << gInit++ << std::endl;
std::cout << "sgInit = " << sgInit++ << std::endl;
}
externprint.h
#ifndef EXTERNPRINT_H_INCLUDED
#define EXTERNPRINT_H_INCLUDED
extern void printStatic();
extern int sgInit; //和內部靜態全域性變數名字不衝突
//extern int gInit; //全域性變數名字衝突
#endif // EXTERNPRINT_H_INCLUDED
externprint.cpp
#include "externPrint.h"
#include "test.h"
#include
int sgInit = 1;
//int gInit = 10;
void printStatic()
{
std::cout << "Gloab_Int = " << ++Gloab_Int << std::endl;
}