C++中的static關(guān)鍵字的總結(jié)

C++的static有兩種用法:面向過程程序設(shè)計中的static和面向?qū)ο蟪绦蛟O(shè)計中的static氢卡。前者應(yīng)用于普通變量和函數(shù),不涉及類晨缴;后者主要說明static在類中的作用译秦。

1.面向過程設(shè)計中的static
1.1靜態(tài)全局變量
在全局變量前,加上關(guān)鍵字static击碗,該變量就被定義成為一個靜態(tài)全局變量筑悴。我們先舉一個靜態(tài)全局變量的例子,如下:
//Example 1

include <iostream.h>

void fn();
static int n; //定義靜態(tài)全局變量
void main()
{
  n=20;
  cout<<n<<endl;
  fn();
}

void fn()
{
   n++;
  cout<<n<<endl;
}
靜態(tài)全局變量有以下特點(diǎn):
? 該變量在全局?jǐn)?shù)據(jù)區(qū)分配內(nèi)存稍途;
? 未經(jīng)初始化的靜態(tài)全局變量會被程序自動初始化為0(自動變量的值是隨機(jī)的阁吝,除非它被顯式初始化);
? 靜態(tài)全局變量在聲明它的整個文件都是可見的械拍,而在文件之外是不可見的突勇;

靜態(tài)變量都在全局?jǐn)?shù)據(jù)區(qū)分配內(nèi)存,包括后面將要提到的靜態(tài)局部變量坷虑。對于一個完整的程序甲馋,在內(nèi)存中的分布情況如下圖: 
代碼區(qū)
全局?jǐn)?shù)據(jù)區(qū)
堆區(qū)
棧區(qū)
一般程序的由new產(chǎn)生的動態(tài)數(shù)據(jù)存放在堆區(qū),函數(shù)內(nèi)部的自動變量存放在棧區(qū)迄损。自動變量一般會隨著函數(shù)的退出而釋放空間定躏,靜態(tài)數(shù)據(jù)(即使是函數(shù)內(nèi)部的靜態(tài)局部變量)也存放在全局?jǐn)?shù)據(jù)區(qū)。全局?jǐn)?shù)據(jù)區(qū)的數(shù)據(jù)并不會因?yàn)楹瘮?shù)的退出而釋放空間芹敌。細(xì)心的讀者可能會發(fā)現(xiàn)痊远,Example 1中的代碼中將 “static int n; //定義靜態(tài)全局變量”改為“int n; //定義全局變量”。程序照樣正常運(yùn)行党窜。的確拗引,定義全局變量就可以實(shí)現(xiàn)變量在文件中的共享,但定義靜態(tài)全局變量還有以下好處:
? 靜態(tài)全局變量不能被其它文件所用幌衣;
? 其它文件中可以定義相同名字的變量矾削,不會發(fā)生沖突壤玫;

您可以將上述示例代碼改為如下:
//Example 2
//File1

include <iostream.h>

void fn();
static int n; //定義靜態(tài)全局變量
void main()
{
  n=20;
  cout<<n<<endl;
  fn();
}

//File2

include <iostream.h>

extern int n;
void fn()
{
   n++;
  cout<<n<<endl;
}
編譯并運(yùn)行Example 2,您就會發(fā)現(xiàn)上述代碼可以分別通過編譯哼凯,但運(yùn)行時出現(xiàn)錯誤欲间。試著將 “static int n; //定義靜態(tài)全局變量”改為 “int n; //定義全局變量”
再次編譯運(yùn)行程序,細(xì)心體會“全局變量”和"靜態(tài)全局變量"的區(qū)別断部。

1.2.靜態(tài)局部變量
在局部變量前猎贴,加上關(guān)鍵字static,該變量就被定義成為一個靜態(tài)局部變量蝴光。 我們先舉一個靜態(tài)局部變量的例子她渴,如下:
//Example 3

include <iostream.h>

void fn();
void main()
{
  fn();
  fn();
  fn();
}
void fn()
{
  static n=10;
  cout<<n<<endl;
   n++;
}
通常,在函數(shù)體內(nèi)定義了一個變量蔑祟,每當(dāng)程序運(yùn)行到該語句時都會給該局部變量分配棧內(nèi)存趁耗。但隨著程序退出函數(shù)體,系統(tǒng)就會收回棧內(nèi)存疆虚,局部變量也相應(yīng)失效苛败。但有時候我們需要在兩次調(diào)用之間對變量的值進(jìn)行保存。通常的想法是定義一個全局變量來實(shí)現(xiàn)径簿。但這樣一來罢屈,變量已經(jīng)不再屬于函數(shù)本身了,不再僅受函數(shù)的控制篇亭,給程序的維護(hù)帶來不便缠捌。
靜態(tài)局部變量正好可以解決這個問題。靜態(tài)局部變量保存在全局?jǐn)?shù)據(jù)區(qū)暗赶,而不是保存在棧中鄙币,每次的值保持到下一次調(diào)用,直到下次賦新值蹂随。
靜態(tài)局部變量有以下特點(diǎn):
? 該變量在全局?jǐn)?shù)據(jù)區(qū)分配內(nèi)存十嘿;
? 靜態(tài)局部變量在程序執(zhí)行到該對象的聲明處時被首次初始化,即以后的函數(shù)調(diào)用不再進(jìn)行初始化岳锁;
? 靜態(tài)局部變量一般在聲明處初始化绩衷,如果沒有顯式初始化,會被程序自動初始化為0激率;
? 它始終駐留在全局?jǐn)?shù)據(jù)區(qū)咳燕,直到程序運(yùn)行結(jié)束。但其作用域?yàn)榫植孔饔糜蚱固桑?dāng)定義它的函數(shù)或語句塊結(jié)束時招盲,其作用域隨之結(jié)束;

1.3靜態(tài)函數(shù)
  在函數(shù)的返回類型前加上static關(guān)鍵字,函數(shù)即被定義為靜態(tài)函數(shù)嘉冒。靜態(tài)函數(shù)與普通函數(shù)不同曹货,它只能在聲明它的文件當(dāng)中可見咆繁,不能被其它文件使用。
靜態(tài)函數(shù)的例子:
//Example 4

include <iostream.h>

static void fn();//聲明靜態(tài)函數(shù)
void main()
{
  fn();
}
void fn()//定義靜態(tài)函數(shù)
{
  int n=10;
  cout<<n<<endl;
}
定義靜態(tài)函數(shù)的好處:
? 靜態(tài)函數(shù)不能被其它文件所用顶籽;
? 其它文件中可以定義相同名字的函數(shù)玩般,不會發(fā)生沖突;

二礼饱、面向?qū)ο蟮膕tatic關(guān)鍵字(類中的static關(guān)鍵字)
2.1靜態(tài)數(shù)據(jù)成員
在類內(nèi)數(shù)據(jù)成員的聲明前加上關(guān)鍵字static坏为,該數(shù)據(jù)成員就是類內(nèi)的靜態(tài)數(shù)據(jù)成員。先舉一個靜態(tài)數(shù)據(jù)成員的例子镊绪。
//Example 5

include <iostream.h>

class Myclass
{
public:
  Myclass(int a,int b,int c);
  void GetSum();
private:
  int a,b,c;
  static int Sum;//聲明靜態(tài)數(shù)據(jù)成員
};
int Myclass::Sum=0;//定義并初始化靜態(tài)數(shù)據(jù)成員

Myclass::Myclass(int a,int b,int c)
{
  this->a=a;
  this->b=b;
  this->c=c;
  Sum+=a+b+c;
}

void Myclass::GetSum()
{
  cout<<"Sum="<<Sum<<endl;
}

void main()
{
  Myclass M(1,2,3);
  M.GetSum();
   Myclass N(4,5,6);
  N.GetSum();
  M.GetSum();

}
可以看出匀伏,靜態(tài)數(shù)據(jù)成員有以下特點(diǎn):
? 對于非靜態(tài)數(shù)據(jù)成員,每個類對象都有自己的拷貝镰吆。而靜態(tài)數(shù)據(jù)成員被當(dāng)作是類的成員帘撰。無論這個類的對象被定義了多少個跑慕,靜態(tài)數(shù)據(jù)成員在程序中也只有一份拷貝万皿,由該類型的所有對象共享訪問。也就是說核行,靜態(tài)數(shù)據(jù)成員是該類的所有對象所共有的牢硅。對該類的多個對象來說,靜態(tài)數(shù)據(jù)成員只分配一次內(nèi)存芝雪,供所有對象共用减余。所以,靜態(tài)數(shù)據(jù)成員的值對每個對象都是一樣的惩系,它的值可以更新位岔;
? 靜態(tài)數(shù)據(jù)成員存儲在全局?jǐn)?shù)據(jù)區(qū)。靜態(tài)數(shù)據(jù)成員定義時要分配空間堡牡,所以不能在類聲明中定義抒抬。在Example 5中,語句int Myclass::Sum=0;是定義靜態(tài)數(shù)據(jù)成員晤柄;
? 靜態(tài)數(shù)據(jù)成員和普通數(shù)據(jù)成員一樣遵從public,protected,private訪問規(guī)則擦剑;
? 因?yàn)殪o態(tài)數(shù)據(jù)成員在全局?jǐn)?shù)據(jù)區(qū)分配內(nèi)存,屬于本類的所有對象共享芥颈,所以惠勒,它不屬于特定的類對象,在沒有產(chǎn)生類對象時其作用域就可見爬坑,即在沒有產(chǎn)生類的實(shí)例時纠屋,我們就可以操作它;
? 靜態(tài)數(shù)據(jù)成員初始化與一般數(shù)據(jù)成員初始化不同盾计。靜態(tài)數(shù)據(jù)成員初始化的格式為:
<數(shù)據(jù)類型><類名>::<靜態(tài)數(shù)據(jù)成員名>=<值>
? 類的靜態(tài)數(shù)據(jù)成員有兩種訪問形式:
<類對象名>.<靜態(tài)數(shù)據(jù)成員名> 或 <類類型名>::<靜態(tài)數(shù)據(jù)成員名>
如果靜態(tài)數(shù)據(jù)成員的訪問權(quán)限允許的話(即public的成員)售担,可在程序中肉康,按上述格式來引用靜態(tài)數(shù)據(jù)成員 ;
? 靜態(tài)數(shù)據(jù)成員主要用在各個對象都有相同的某項(xiàng)屬性的時候灼舍。比如對于一個存款類吼和,每個實(shí)例的利息都是相同的。所以骑素,應(yīng)該把利息設(shè)為存款類的靜態(tài)數(shù)據(jù)成員炫乓。這有兩個好處,第一献丑,不管定義多少個存款類對象末捣,利息數(shù)據(jù)成員都共享分配在全局?jǐn)?shù)據(jù)區(qū)的內(nèi)存,所以節(jié)省存儲空間创橄。第二箩做,一旦利息需要改變時,只要改變一次妥畏,則所有存款類對象的利息全改變過來了邦邦;
? 同全局變量相比,使用靜態(tài)數(shù)據(jù)成員有兩個優(yōu)勢:

  1. 靜態(tài)數(shù)據(jù)成員沒有進(jìn)入程序的全局名字空間醉蚁,因此不存在與程序中其它全局名字沖突的可能性燃辖;
  2. 可以實(shí)現(xiàn)信息隱藏。靜態(tài)數(shù)據(jù)成員可以是private成員网棍,而全局變量不能黔龟;

2.2靜態(tài)成員函數(shù)
  與靜態(tài)數(shù)據(jù)成員一樣,我們也可以創(chuàng)建一個靜態(tài)成員函數(shù)滥玷,它為類的全部服務(wù)而不是為某一個類的具體對象服務(wù)氏身。靜態(tài)成員函數(shù)與靜態(tài)數(shù)據(jù)成員一樣,都是類的內(nèi)部實(shí)現(xiàn)惑畴,屬于類定義的一部分蛋欣。普通的成員函數(shù)一般都隱含了一個this指針,this指針指向類的對象本身桨菜,因?yàn)槠胀ǔ蓡T函數(shù)總是具體的屬于某個類的具體對象的豁状。通常情況下,this是缺省的倒得。如函數(shù)fn()實(shí)際上是this->fn()泻红。但是與普通函數(shù)相比,靜態(tài)成員函數(shù)由于不是與任何的對象相聯(lián)系霞掺,因此它不具有this指針谊路。從這個意義上講,它無法訪問屬于類對象的非靜態(tài)數(shù)據(jù)成員菩彬,也無法訪問非靜態(tài)成員函數(shù)缠劝,它只能調(diào)用其余的靜態(tài)成員函數(shù)潮梯。下面舉個靜態(tài)成員函數(shù)的例子。
//Example 6

include <iostream.h>

class Myclass
{
public:
  Myclass(int a,int b,int c);
  static void GetSum();/聲明靜態(tài)成員函數(shù)
private:
  int a,b,c;
   static int Sum;//聲明靜態(tài)數(shù)據(jù)成員
};
int Myclass::Sum=0;//定義并初始化靜態(tài)數(shù)據(jù)成員

Myclass::Myclass(int a,int b,int c)
{
  this->a=a;
  this->b=b;
  this->c=c;
  Sum+=a+b+c; //非靜態(tài)成員函數(shù)可以訪問靜態(tài)數(shù)據(jù)成員
}

void Myclass::GetSum() //靜態(tài)成員函數(shù)的實(shí)現(xiàn)
{
  // cout<<a<<endl; //錯誤代碼惨恭,a是非靜態(tài)數(shù)據(jù)成員
  cout<<"Sum="<<Sum<<endl;
}

void main()
{
  Myclass M(1,2,3);
  M.GetSum();
  Myclass N(4,5,6);
  N.GetSum();
  Myclass::GetSum();
}
關(guān)于靜態(tài)成員函數(shù)秉馏,可以總結(jié)為以下幾點(diǎn):
? 出現(xiàn)在類體外的函數(shù)定義不能指定關(guān)鍵字static;
? 靜態(tài)成員之間可以相互訪問脱羡,包括靜態(tài)成員函數(shù)訪問靜態(tài)數(shù)據(jù)成員和訪問靜態(tài)成員函數(shù)萝究;
? 非靜態(tài)成員函數(shù)可以任意地訪問靜態(tài)成員函數(shù)和靜態(tài)數(shù)據(jù)成員;
? 靜態(tài)成員函數(shù)不能訪問非靜態(tài)成員函數(shù)和非靜態(tài)數(shù)據(jù)成員锉罐;
? 由于沒有this指針的額外開銷帆竹,因此靜態(tài)成員函數(shù)與類的全局函數(shù)相比速度上會有少許的增長;
? 調(diào)用靜態(tài)成員函數(shù)脓规,可以用成員訪問操作符(.)和(->)為一個類的對象或指向類對象的指針調(diào)用靜態(tài)成員函數(shù)栽连,也可以直接使用如下格式:
<類名>::<靜態(tài)成員函數(shù)名>(<參數(shù)表>)
調(diào)用類的靜態(tài)成員函數(shù)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末侨舆,一起剝皮案震驚了整個濱河市秒紧,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌态罪,老刑警劉巖噩茄,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異复颈,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)沥割,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進(jìn)店門耗啦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人机杜,你說我怎么就攤上這事帜讲。” “怎么了椒拗?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵似将,是天一觀的道長。 經(jīng)常有香客問我蚀苛,道長在验,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任堵未,我火速辦了婚禮腋舌,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘渗蟹。我一直安慰自己块饺,他們只是感情好赞辩,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著授艰,像睡著了一般辨嗽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上淮腾,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天召庞,我揣著相機(jī)與錄音,去河邊找鬼来破。 笑死篮灼,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的徘禁。 我是一名探鬼主播诅诱,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼送朱!你這毒婦竟也來了娘荡?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤驶沼,失蹤者是張志新(化名)和其女友劉穎炮沐,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體回怜,經(jīng)...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡大年,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了玉雾。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片翔试。...
    茶點(diǎn)故事閱讀 40,488評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖复旬,靈堂內(nèi)的尸體忽然破棺而出垦缅,到底是詐尸還是另有隱情,我是刑警寧澤驹碍,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布壁涎,位于F島的核電站,受9級特大地震影響志秃,放射性物質(zhì)發(fā)生泄漏怔球。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一洽损、第九天 我趴在偏房一處隱蔽的房頂上張望庞溜。 院中可真熱鬧,春花似錦、人聲如沸流码。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽漫试。三九已至六敬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間驾荣,已是汗流浹背蛇耀。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工媒至, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留活逆,地道東北人猜煮。 一個月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像歧匈,于是被迫代替她去往敵國和親垒酬。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 一直使用static,但沒用總結(jié)過件炉,時間一長概念總有點(diǎn)模糊勘究,趁著這次機(jī)會總結(jié)一下。c++中:C++中static有...
    被代碼淹沒的小伙子閱讀 521評論 0 0
  • 1. 結(jié)構(gòu)體和共同體的區(qū)別斟冕。 定義: 結(jié)構(gòu)體struct:把不同類型的數(shù)據(jù)組合成一個整體口糕,自定義類型。共同體uni...
    breakfy閱讀 2,130評論 0 22
  • C++ 的 static 有兩種用法: 面向過程程序設(shè)計中的static 和面向?qū)ο蟪绦蛟O(shè)計中的 static. ...
    夜殤丶夜逝閱讀 677評論 0 0
  • C++關(guān)鍵字的思考 本章內(nèi)容:1 關(guān)鍵字的相關(guān)理解1.1 const關(guān)鍵字1.2 static關(guān)鍵字1.3 非局部...
    Haley_2013閱讀 778評論 0 50
  • 某天的某一刻磕蛇,我無可救藥的愛上了你景描,自那以后,睜開眼的第一件事孤里,便是想你伏伯,可我也深深的明白,你終究會成為我生命里的...
    孤楓塵閱讀 689評論 0 3