C++ 類中static成員的初始化和特點
在C++的類中有些成員變數初始化和一般資料類型的成員變數有所不同。以下測試編譯環境為:
➜ g++ -vUsing built-in specs.COLLECT_GCC=g++Target: x86_64-linux-gnugcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4)
測試代碼(g++編譯通過):
#include <iostream>using namespace std;class Test{public: Test() : y(1), r(y), d(3){} //對於常量型成員變數和引用型成員變數,必須通過參數化列表的方式進行初始化。 ~Test(){} int y; //普通變數成員 int &r; //引用成員變數 const int d; //常量成員變數 static int c; //靜態成員變數 static const int x = 2.1; //靜態常量整型成員變數 static const int xx; //靜態常量整型成員變數聲明 static const double z; //靜態常量非整型成員變數聲明 static const float zz = 6.6; //靜態常量非整型成員變數};const int Test::xx = 4; //靜態常量整型成員變數定義const double Test::z = 5.1; ////靜態常量非整型成員變數定義int Test::c = 2;int main(void){ cout << Test::x << endl; return 0;}
這些特殊類型的成員變數主要有:
1. 引用2. 常量3. 靜態變數4. 靜態整型常量5. 靜態非整型常量
對於==1. 引用==和==2. 常量==,成員變數必須通過建構函式的==參數列表==的方式初始化。例如:上述程式中的r 和 d 變數的初始化。
對於==3. 靜態變數==,static成員變數需要在類定義體外進行初始化與定義,因為static資料成員獨立該類的任意對象存在,它是與類關聯的對象,不與類對象關聯。例如:上述程式中的c變數的初始化。
對於==4. 靜態整型常量==,該類型成員可以直接在類中初始化,也可以在類中聲明,在類定義體外進行定義。例如:上述程式中的x和xx變數。
對於==5. 靜態非整型常量==,該類型也是可以在類中聲明在類定義體外進行定義,或者直接在類中定義初始化。例如:上述程式中的z和zz變數。
結論:
靜態成員屬於類範圍,但不屬於類對象,它的生命週期和普通的靜態變數一樣,程式運行時進行分配記憶體和初始化,程式結束時則被釋放。所以不能在類的建構函式中進行初始化。
static成員的優點
- static成員的名字是在類的範圍中,因此可以避免與其它類成員或全域對象名字衝突。
- 可以實施封裝,static成員可以是私人的,而全域對象不可以。
- 閱讀程式容易看出static成員與某個類相關聯,這種可見度可以清晰地反映程式員的意圖。
static成員函數特點
- 因為static成員函數沒有this指標,所以靜態成員函數不可以訪問非靜態成員。
- 非靜態成員函數可以訪問靜態成員。
- 待用資料成員與類的大小無關,因為靜態成員只是作用在類的範圍而已。
#include <iostream>using namespace std;class test2{public: test2(int num) : y(num){} ~test2(){} static void testStaticFun() { cout << "y = " << y << endl; //Error:靜態成員函數不能訪問非靜態成員 } void testFun() { cout << "x = " << x << endl; }private: static int x;//靜態成員變數的引用性說明 int y;};int test2::x = 10;//靜態成員變數的定義性說明int main(void){ test2 t(100); t.testFun(); return 0;}
static用法總結
- c語言中:
- 用於函數內部修飾變數,即函數內的靜態變數。這種變數的生存期長於該函數,使得函數具有一定的“狀態”。使用靜態變數的函數一般是不可重新進入的,也不是安全執行緒的,比如strtok(3)。
- 用在檔案層級(函數體之外),修飾變數或函數,表示該變數或函數只在本檔案可見,其他檔案看不到也訪問不到該變數或函數。專業的說法叫“具有internal linkage”(簡言之:不暴露給別的translation unit)。
- c++語言中(由於C++引入了類,在保持與C語言相容的同時,static關鍵字又有了兩種新用法):
- 用於修飾類的資料成員,即所謂“靜態成員”。這種資料成員的生存期大於class的對象(執行個體/instance)。待用資料成員是每個class有一份,普通資料成員是每個instance 有一份。
- 用於修飾class的成員函數,即所謂“靜態成員函數”。這種成員函數只能訪問靜態成員和其他靜態程員函數,不能訪問非靜態成員和非靜態成員函數。