??數(shù)據(jù)成員可以分為靜態(tài)變量庞溜、非靜態(tài)變量兩種。
??靜態(tài)成員:靜態(tài)類中的成員加入static修飾符碑定,即是靜態(tài)成員流码,可以使用類名+靜態(tài)成員名訪問此靜態(tài)成員,因為靜態(tài)成員存在于內(nèi)存延刘,非靜態(tài)成員需要實例化才會分配內(nèi)存漫试,所以 靜態(tài)成員不能訪問非靜態(tài)成員,因為靜態(tài)成員存在于內(nèi)存碘赖,所以非靜態(tài)成員可以直接訪問類中的靜態(tài)成員商虐。
??非靜態(tài)成員:所有沒有加static的成員都是非靜態(tài)成員,當類被實例化后崖疤,可以通過實例化的類名進行訪問秘车,非靜態(tài)成員的生存期決定于該類的生存期,而靜態(tài)成員則不存在生存期的概念劫哼,因為靜態(tài)成員始終駐留在內(nèi)存中叮趴。
??一個類中可以包含靜態(tài)成員和非靜態(tài)成員,類中也包括靜態(tài)構造函數(shù)和非靜態(tài)構造函數(shù)权烧。
以下分兩方面來說眯亦,第一方面主要是相對于面向過程而言,在這方面不涉及類般码;另一方面相對于面向?qū)ο髞碚f妻率,主要說明static在類中的作用。
一板祝、在面向過程設計中的static關鍵字
1宫静、靜態(tài)全局變量
定義:在全局變量前加上關鍵字static,該變量就被定義成一個靜態(tài)全局變量。
特點:
?? A 孤里、該變量在全局數(shù)據(jù)區(qū)分配內(nèi)存
?? B伏伯、初始化:如果不顯式初始化,那么將被飲食初始化為0(自動變量是隨機的捌袜,除非是顯式初始化)
?? C说搅、該變量只在本源文件可見,嚴格地講虏等,應該從定義之處開始到本文件結束弄唧。
1. #include <iostream>
3. using namespace std;
5. void fun();
7. static int n;
9. void main()
10. {
11. n = 20;
12. cout<<n<<endl;
13. fun();
15. }
17. void fun()
18. {
19. n++;
20. cout<<n<<endl;
21. }
??????????????????????輸出 20 21
??D、文件作用域下聲明的const的常量默認為static存儲類型霍衫。
????靜態(tài)變量都在全局數(shù)據(jù)區(qū)分配內(nèi)存套才,包括靜態(tài)局部變量。對于一個完整的程序慕淡,在內(nèi)存中的分布情況如下:
????代碼區(qū)
????全局數(shù)據(jù)區(qū)
????堆區(qū)
????棧區(qū)
??一般在程序中,由new產(chǎn)生的動態(tài)數(shù)據(jù)區(qū)放在堆區(qū)中沸毁,函數(shù)內(nèi)部的自動變量存放在棧區(qū)峰髓。自動變量一般會隨著函數(shù)的退出而釋放空間,靜態(tài)數(shù)據(jù)(即使是函數(shù)內(nèi)部的靜態(tài)局部變量)也存放在全局數(shù)據(jù)區(qū)中息尺。全局數(shù)據(jù)區(qū)的數(shù)據(jù)并不會因為函數(shù)的退出而釋放空間携兵。
??如果把上例中的
????static int n;修改為
????nt n搂誉;//全局變量徐紧。它可以實現(xiàn)變量在文件中的共享
??但是靜態(tài)全局變量有以下好處:
????在其他文件中可以定義相同名字的變量,而不會發(fā)生沖突炭懊。
#include <iostream>
using namespace std;
void fun();
static int n;
void main()
{
n = 20;
cout<<n<<endl;
fun();
}
FILE 2
#include <iostream>
using namespace std;
extern int n;
void fun()
{
n++;
cout<<n<<endl;
}
2并级、靜態(tài)局部變量
定義:在局部變量前加上static關鍵字時,就定義了靜態(tài)局部變量侮腹。
1. FILE 3
2. #include <iostream>
4. using namespace std;
6. void fun();
8. void main()
9. {
10. fun();
11. fun();
12. fun();
14. }
16. void fun()
17. {
18. static int n = 10;
19. n++;
20. cout<<n<<endl;
21. }
??通常嘲碧,在函數(shù)體內(nèi)定義了一個變量,每當程序運行到該語句時都會給該局部變量分配棧內(nèi)存父阻,但隨著程序退出函數(shù)體愈涩,系統(tǒng)就會收回棧內(nèi)存,局部變量也相應失效加矛。但是有時候我們需要在兩次調(diào)用之間對變量的值進行保存履婉,通常的想法是定義一個全局變量來實現(xiàn),但是這樣一來斟览,變量已經(jīng)不再屬于函數(shù)本身了毁腿,不再僅受函數(shù)的控制,給程序的維護帶來不便。
??靜態(tài)局部變量正好可以解決這個問題狸棍。靜態(tài)局部變量保存在全局數(shù)據(jù)區(qū)身害,而不是保存在棧中,每次的值保持到下一次調(diào)用草戈,直到下次賦新值塌鸯。
特點:
A、該變量在全局數(shù)據(jù)區(qū)分配內(nèi)存
B唐片、初始化:如果不是顯式初始化丙猬,那么將被隱式初始化為0,以后的函數(shù)調(diào)用不再進行初始化费韭。
C茧球、它始終駐留在全局數(shù)據(jù)區(qū),直到程序運行結束星持。但其作用域為局部作用域抢埋。當定義它的函數(shù)或語句塊結束時,其作用域也隨之結束督暂。
3揪垄、靜態(tài)函數(shù)與普通函數(shù)不同,它只能在聲明它的文件當中可見逻翁,不能被其他文件使用申眼。
1. FILE 4
2. #include <iostream>
4. using namespace std;
6. static void fun();
8. void main()
9. {
10. fun();
12. }
14. void fun()
15. {
16. int n = 10;
17. n++;
18. cout<<n<<endl;
19. }
定義靜態(tài)函數(shù)的好處:靜態(tài)函數(shù)不能被其他文件使用掀序。在其他文件中可以定義相同名字的函數(shù)们何,不會發(fā)生沖突吩坝。
二、面向?qū)ο蟮膕tatic關鍵字
1缠诅、靜態(tài)數(shù)據(jù)成員
在類內(nèi)數(shù)據(jù)成員的聲明前加上關鍵字static溶浴,該數(shù)據(jù)成員就是類內(nèi)的靜態(tài)數(shù)據(jù)成員。
[cpp] [view plain](http://blog.csdn.net/kerry0071/article/details/25741425/#) [copy](http://blog.csdn.net/kerry0071/article/details/25741425/#)
1. #include <iostream>
3. using namespace std;
5. class MyClass
6. {
7. public:
8. MyClass(int a, int b, int c);
9. void fun();
10. private:
11. int a,b,c;
12. static int sum;//聲明靜態(tài)數(shù)據(jù)成員
13. };
15. int MyClass::sum = 0;
16. MyClass::MyClass(int a, int b, int c)
17. {
18. this->a = a;
19. this->b = b;
20. this->c = c;
21. sum += a+b+c;
22. }
24. void MyClass::fun()
25. {
26. cout<<"sum = "<<sum<<endl;
27. }
28. void main()
29. {
30. MyClass M(1,2,3);
31. M.fun();
33. MyClass N(4,5,6);
34. N.fun();
35. }
??從以上的程序可以看出管引,靜態(tài)數(shù)據(jù)成員有以下特點:
??對于非靜態(tài)數(shù)據(jù)成員戳葵,每個類對象都有自己的拷貝。而靜態(tài)數(shù)據(jù)成員被當作是類的成員汉匙。無論這個類的對象定義了多少個拱烁,靜態(tài)數(shù)據(jù)成員在程序中也只有一份拷貝,由該類型的所有對象共享訪問噩翠。即靜態(tài)數(shù)據(jù)成員是該類的所有對象所共有的戏自。對該類的多個對象來說,靜態(tài)數(shù)據(jù)成員只分配一次內(nèi)存伤锚,供所有對象共用擅笔。所以,靜態(tài)數(shù)據(jù)成員的值對每個對象都是一樣的,它的值可以更新猛们。
??靜態(tài)數(shù)據(jù)成員存儲在全局數(shù)據(jù)區(qū)念脯,靜態(tài)數(shù)據(jù)成員定義時要分配空間,所以不能在類聲明中定義弯淘。應該在類外定義绿店。
??靜態(tài)數(shù)據(jù)成員和普通數(shù)據(jù)成員一樣遵從public、private庐橙、protected訪問規(guī)則假勿。
??由于靜態(tài)數(shù)據(jù)成員在全局數(shù)據(jù)區(qū)分配內(nèi)存,屬于本類的所有對象共享态鳖,它不屬于特定的類對象转培,在沒有產(chǎn)生類對象時作用域就可見。即在沒有產(chǎn)生類的實例時浆竭,我們就可以操作它浸须。靜態(tài)數(shù)據(jù)成員的初始化與一般數(shù)據(jù)成員的初始化不同,即它的初始化格式為:
????<數(shù)據(jù)類型><類名>::<靜態(tài)數(shù)據(jù)成員> = <值>
??類的靜態(tài)數(shù)據(jù)成員有兩種訪問方式:
??如果靜態(tài)數(shù)據(jù)成員的訪問權限允許的話邦泄,即為public成員删窒,可在程序中,按上述格式來引用靜態(tài)數(shù)據(jù)成員虎韵;
??靜態(tài)數(shù)據(jù)成員主要用在各個對象都有相同的某項屬性的時候。比如對一個存款類缸废,每個實例的利息都是相同的包蓝,所以把利息可以設為存款類的靜態(tài)數(shù)據(jù)成員。這有兩個好處企量,一是不管定義多少個存款類對象测萎,利息數(shù)據(jù)成員都共享分配在全局數(shù)據(jù)區(qū)的內(nèi)存,所以節(jié)省了存儲空間届巩。二是一旦利息需要改變時硅瞧,只要改變一次,則所有存款類對象的利息全改變過來了恕汇。
??同全局變量相比腕唧,使用靜態(tài)數(shù)據(jù)成員有兩個優(yōu)勢:
(1)靜態(tài)數(shù)據(jù)成員沒有進入程序的全局名字空間,因此不存在與程序中其他全局名字沖突的可能性瘾英;
(2)可以實現(xiàn)信息隱藏枣接。靜態(tài)數(shù)據(jù)成員可以使private成員,而全局變量不能缺谴。
4但惶、靜態(tài)成員函數(shù)
??與靜態(tài)數(shù)據(jù)成員一樣,我們也可以創(chuàng)建一個靜態(tài)成員函數(shù),它為類的全部服務膀曾,而不是為某一個類的具體對象服務县爬。靜態(tài)成員函數(shù)與靜態(tài)數(shù)據(jù)成員一樣,都是在類的內(nèi)部實現(xiàn)添谊,屬于類定義的一部分财喳。普通的成員函數(shù)一般都隱藏了一個this指針,this指針指向類的對象本身碉钠,因為普通成員函數(shù)總是具體的屬于某個類的具體對象的纲缓。通常情況下,this指針是缺省的喊废、但是與普通函數(shù)相比祝高,靜態(tài)成員函數(shù)由于不是與任何的對象相聯(lián)系,因此它不具有this指針污筷,從這個意義上講工闺,它無法訪問屬于類對象的非靜態(tài)數(shù)據(jù)成員,也無法訪問非靜態(tài)成員函數(shù)瓣蛀,它只能調(diào)用其余的靜態(tài)成員函數(shù)陆蟆。
1. #include <iostream>
3. using namespace std;
5. class MyClass
6. {
7. public:
8. MyClass(int a, int b, int c);
9. static void fun();
10. private:
11. int a,b,c;
12. static int sum;//聲明靜態(tài)數(shù)據(jù)成員
13. };
15. int MyClass::sum = 0;
16. MyClass::MyClass(int a, int b, int c)
17. {
18. this->a = a;
19. this->b = b;
20. this->c = c;
21. sum += a+b+c;
22. }
24. void MyClass::fun()
25. {
26. cout<<"sum = "<<sum<<endl;
27. }
28. void main()
29. {
30. MyClass M(1,2,3);
31. M.fun();
33. MyClass N(4,5,6);
34. N.fun();
35. MyClass::fun();//靜態(tài)成員函數(shù)的訪問
36. }
關于靜態(tài)成員函數(shù),可以總結以下幾點:
(1)出現(xiàn)在類體外的函數(shù)不能指定關鍵字static惋增;(類的成員函數(shù)叠殷,在類外定義,不需要(也不能)加static關鍵字)
(2)靜態(tài)成員之間可以互相訪問诈皿,包括靜態(tài)成員函數(shù)訪問靜態(tài)數(shù)據(jù)成員和訪問靜態(tài)成員函數(shù)林束;
(3)非靜態(tài)成員函數(shù)可以任意地訪問靜態(tài)成員函數(shù)和靜態(tài)數(shù)據(jù)成員;
(4)靜態(tài)成員函數(shù)不能訪問非靜態(tài)成員函數(shù)和非靜態(tài)數(shù)據(jù)成員稽亏;
(5)由于沒有this指針的額外開銷壶冒,因此靜態(tài)成員函數(shù)與類的全局函數(shù)相比,速度上會有少許的增長截歉;
(6)調(diào)用靜態(tài)成員函數(shù)胖腾,可以用成員訪問操作符(.)和(->)為一個類的對象或指向類對象的指調(diào)用靜態(tài)成員函數(shù)。
靜態(tài)函數(shù)主要為了調(diào)用方便瘪松,不需要生成對象就能調(diào)用