引言
? ? ? ?static關(guān)鍵字在c/c++中的使用是十分廣泛的礁蔗。該關(guān)鍵字的作用很多突硝,其中一個(gè)最常用的作用就是對(duì)函數(shù)或者變量進(jìn)行隱藏:沒有添加static的變量或者函數(shù)是全局可見的螃宙;而添加了static關(guān)鍵字的全局變量則被隱藏蛮瞄,利用這一特性可以在不同的文件中定義同名函數(shù)和同名變量,而不必?fù)?dān)心命名沖突谆扎。
? ? ? ?現(xiàn)在挂捅,如果想在.h文件中定義static變量,將它強(qiáng)行暴露出來堂湖,會(huì)發(fā)生什么情況呢闲先?為了解決這一疑惑,筆者在windows下的vs2010環(huán)境中進(jìn)行了試驗(yàn)无蜂。
Context
試驗(yàn)一:
? ? ? ?筆者現(xiàn)在創(chuàng)建一個(gè)工程目錄伺糠,目錄結(jié)構(gòu)如下:
~/workspace/Test
|-src
| |-A.h
| |-B.h
| |-main.cpp
| |-B.cpp
|-doc
| |-Test.txt
|-COPYRIGHT
|-README
? ? ? ?頭文件A.h,主要作用是在頭文件A中定義了static變量a斥季,將變量a暴露出來训桶。
#ifndef _A_H_
#define _A_H_
static int a=0;
#endif
? ? ? ?頭文件B.h,聲明了函數(shù)funB()酣倾,同時(shí)引入了頭文件A.h舵揭。
#ifndef _B_H_
#define _B_H_
#include "A.h"
void funB();
#endif
? ? ? ?B.cpp文件,定義了函數(shù)funB()躁锡。
#include "B.h"
#include<iostream>
using namespace std;
void funB()
{
cout<<"funB(): &a = "<<&a<<" , a = "<<a<<endl;
}
? ? ? ?main.cpp文件午绳。
#include <iostream>
#include "A.h"
#include "B.h"
using namespace std;
int main()
{
cout<<"main1(): &a = "<<&a<<" , a = "<<a<<endl;
a++;
cout<<"main2(): &a = "<<&a<<" , a = "<<a<<endl;
funB();
system("pause");
return 0;
}
? ? ? ?因?yàn)閍定義在.h文件中,如果a是一個(gè)全局變量稚铣,對(duì)于main.cpp和B.cpp都是可見的箱叁,那么在main函數(shù)中,a的值應(yīng)該先為0惕医,在main的末尾耕漱,應(yīng)該為1,且a的地址都應(yīng)該是一樣的抬伺,但是螟够,vs2010顯示的結(jié)果如下:
? ? ? ?結(jié)果表明,mian.cpp讀取的a和B.cpp讀取的變量a是兩個(gè)不同的變量,擁有不同的地址空間妓笙,a在main.cpp和B.cpp中做到了互相獨(dú)立若河。也就是說定義在頭文件里的static變量,被其他模塊每包含一次就申請(qǐng)一次內(nèi)存寞宫!
試驗(yàn)二:
? ? ? ?保持其他文件不變萧福,只改變A.h中的static int a =0;
。將這句話改為 int a = 0;
辈赋,此時(shí)鲫忍,工程無法通過編譯,會(huì)報(bào)fatal error LNK1169: one or more multiply defined symbols found
錯(cuò)誤钥屈,這個(gè)很好理解悟民,因?yàn)闆]有static修飾后的變量a是一個(gè)全局變量,在main.cpp中和B.cpp中在全局空間中同時(shí)定義了兩個(gè)名字相同的變量篷就,會(huì)導(dǎo)致重定義的錯(cuò)誤射亏。同時(shí)結(jié)合試驗(yàn)一也再一次論證了舌菜,全局變量#include多次會(huì)出錯(cuò)士葫,而static變量被#include多次會(huì)生成多個(gè)局部變量运挫。
試驗(yàn)三:
? ? ? ?筆者現(xiàn)在創(chuàng)建一個(gè)新的工程目錄迟几,目錄結(jié)構(gòu)如下:
~/workspace/Test
|-src
| |-B.h
| |-main.cpp
| |-B.cpp
|-doc
| |-Test.txt
|-COPYRIGHT
|-README
? ? ? ?頭文件B.h身辨。
#ifndef _B_H_
#define _B_H_
void funB();
#endif
? ? ? ?B.cpp文件匕垫,定義了函數(shù)funB()雏门。
#include "B.h"
#include<iostream>
using namespace std;
static int a = 0;
void funB()
{
cout<<"funB(): &a = "<<&a<<" , a = "<<a<<endl;
}
? ? ? ?main.cpp文件泞莉。
#include <iostream>
#include "A.h"
#include "B.h"
using namespace std;
extern int a;
int main()
{
cout<<"main1(): &a = "<<&a<<" , a = "<<a<<endl;
a++;
cout<<"main2(): &a = "<<&a<<" , a = "<<a<<endl;
funB();
system("pause");
return 0;
}
? ? ? ?此時(shí)也會(huì)編譯報(bào)錯(cuò)鼎姐,報(bào)fatal error LNK1120: 1 unresolved externals
钾麸,因?yàn)閟tatic關(guān)鍵字修飾了變量a,使得變量a是B.cpp獨(dú)占的炕桨,對(duì)main.cpp隱藏饭尝,即使用extern關(guān)鍵字修飾,main.cpp也無法解析献宫。
試驗(yàn)四:
? ? ? ?試驗(yàn)四在試驗(yàn)三的基礎(chǔ)上钥平,將B.cpp中的static int a = 0;
修改為int a = 0;
。缺少了static關(guān)鍵字修飾姊途,利用extern自然可以將B.cpp中的a暴露給 main.cpp涉瘾。
? ? ? ?試驗(yàn)結(jié)果如下:
總結(jié)
? ? ? ?上述的四次試驗(yàn)再一次證明了:變量不要在頭文件中定義,要在.cpp文件中定義捷兰!全局變量#include多次會(huì)出錯(cuò)立叛,而static變量被#include多次會(huì)生成多個(gè)局部變量。