靜態成員的提出是為了解決數據共享的問題。實現共享有許多方法,如:設置全局性的變量或對象是一種方法。但是,全局變量或對象是有局限性的。這一章里,我們主要講述類的靜態成員來實現數據的共享。
靜態數據成員
在類中,靜態成員可以實現多個對象之間的數據共享,並且使用靜態數據成員還不會破壞隱藏的原則,即保證了安全性。因此,靜態成員是類的所有對象中共享的成員,而不是某個對象的成員。
使用靜態數據成員可以節省內存,因為它是所有對象所公有的,因此,對多個對象來說,靜態數據成員只存儲一處,供所有對象共用。靜態數據成員的值對每個對象都是一樣,但它的值是可以更新的。只要對靜態數據成員的值更新一次,保證所有對象存取更新后的相同的值,這樣可以提高時間效率。
靜態數據成員的使用方法和注意事項如下:
1、靜態數據成員在定義或說明時前面加關鍵字static。//靜態變量的定義
2、靜態成員初始化與一般數據成員初始化不同。靜態數據成員初始化的格式如下:
<數據類型><類名>::<靜態數據成員名>=<值> //靜態變量的初始化
這表明:
(1) 初始化在類體外進行,而前面不加static,(這點需要注意)以免與一般靜態變量或對象相混淆。
(2) 初始化時不加該成員的訪問權限控制符private,public等。
(3) 初始化時使用作用域運算符來標明它所屬類,因此,靜態數據成員是類的成員,而不是對象的成員。
3、靜態數據成員是靜態存儲的,它是靜態生存期,必須對它進行初始化。
4、引用靜態數據成員時,采用如下格式:
<類名>::<靜態成員名> //靜態變量的使用方式
如果靜態數據成員的訪問權限允許的話(即public的成員),可在程序中,按上述格式來引用靜態數據成員。
下面舉一例子,說明靜態數據成員的應用:
1 class StaticTest 2 { 3 public: 4 StaticTest(int a, int b, int c); 5 void GetNumber(); 6 void GetSum(); 7 static void f1(StaticTest &s); 8 private: 9 int A, B, C; 10 static int Sum; 11 }; 12 13 14 15 #include "StaticTest.h" 16 #include <iostream> 17 using namespace std; 18 19 int StaticTest::Sum = 0;//靜態成員在此初始化 20 21 StaticTest::StaticTest(int a, int b, int c) 22 { 23 A = a; 24 B = b; 25 C = c; 26 Sum += A + B + C; 27 } 28 29 void StaticTest::GetNumber() 30 { 31 cout << "Number = " << endl; 32 } 33 34 void StaticTest::GetSum() 35 { 36 cout << "Sum = " << Sum <<endl; 37 } 38 39 void StaticTest::f1(StaticTest &s) 40 { 41 42 cout << s.A << endl;//靜態方法不能直接調用一般成員,可以通過對象引用實現調用 43 cout << Sum <<endl; 44 } 45 46 #include "StaticTest.h" 47 #include <stdlib.h> 48 49 50 int main(void) 51 { 52 StaticTest M(3, 7, 10), N(14, 9, 11); 53 M.GetNumber(); 54 N.GetSum(); 55 M.GetNumber(); 56 N.GetSum(); 57 StaticTest::f1(M); 58 system("pause"); 59 return 0; 60 }
注意,static成員的初始化要在實現中進行,不能在頭文件進行。
從輸出結果可以看到Sum的值對M對象和對N對象都是相等的。這是因為在初始化M對象時,將M對象的三個int型數據成員的值求和后賦給了Sum,於是Sum保存了該值。在初始化N對象時,對將N對象的三個int型數據成員的值求和后又加到Sum已有的值上,於是Sum將保存另后的值。所以,不論是通過對象M還是通過對象N來引用的值都是一樣的,即為54,s.A=3。
靜態成員函數
靜態成員函數和靜態數據成員一樣,它們都屬於類的靜態成員,它們都不是對象成員。因此,對靜態成員的引用不需要用對象名。
在靜態成員函數的實現中不能直接引用類中說明的非靜態成員,可以引用類中說明的靜態成員(這點非常重要)。如果靜態成員函數中要引用非靜態成員時,可通過對象來引用。從中可看出,調用靜態成員函數使用如下格式:<類名>::<靜態成員函數名>(<參數表>);