int foo(){ static int i = 1; // note:1 //int i = 1; // note:2 i += 1; return i; }
static int i = 1; //note:3 //int i = 1; //note:4 int foo() { i += 1; return i; }
假設我有一個文件a.c,我們再新建一個b.c,內容如下。
//file a.c //static int n = 15; //note:5 int n = 15; //note:6 //file b.c #includeextern int n; void fn() { n++; printf(after: %d ,n); } void main() { printf(before: %d ,n); fn(); }
gcc a.c b.c -o output.out
會出現類似undeference to n的報錯,它是找不到n的,因為static進行了文件隔離,你是沒辦法訪問a.c定義的靜態全局變量的,當然你用 #include a.c,那就不一樣了。
以上我們就可以得出靜態全局變量的特點:
靜態全局變量不能被其它文件所用(全局變量可以);//file a.c #includevoid fn() { printf(this is non-static func in a); } //file b.c #include extern void fn(); //我們用extern聲明其他文件的fn(),供本文件使用。 void main() { fn(); }
#includeusing namespace std; class Rectangle { private: int m_w,m_h; static int s_sum; public: Rectangle(int w,int h) { this->m_w = w; this->m_h = h; s_sum += (this->m_w * this->m_h); } void GetSum() { cout< GetSum(); cout< 結果如下:
由圖可知:sizeof(Rectangle)=8bytes=sizeof(m_w)+sizeof(m_h)。也就是說 static 並不占用Rectangle的內存空間。 那麼static在哪裡分配內存的呢?是的,全局數據區(靜態區)。 再看看GetSum(),第一次12=3*4,第二次18=12+2*3。由此可得,static只會被初始化一次,於實例無關。結論:
對於非靜態數據成員,每個類對象(實例)都有自己的拷貝。而靜態數據成員被當作是類的成員,由該類型的所有對象共享訪問,對該類的多個對象來說,靜態數據成員只分配一次內存。 靜態數據成員存儲在全局數據區。靜態數據成員定義時要分配空間,所以不能在類聲明中定義。 也就是說,你每new一個Rectangle,並不會為static int s_sum的構建一份內存拷貝,它是不管你new了多少Rectangle的實例,因為它只與類Rectangle掛鉤,而跟你每一個Rectangle的對象沒關系。
2、靜態成員函數:用於修飾 class 的成員函數。 我們對上面的例子稍加改動:#includeusing namespace std; class Rectangle { private: int m_w,m_h; static int s_sum; public: Rectangle(int w,int h) { this->m_w = w; this->m_h = h; s_sum += (this->m_w * this->m_h); } static void GetSum() //這裡加上static { cout< GetSum(); cout< 上面注釋可見:對GetSum()加上static,使它變成一個靜態成員函數,可以用類名::函數名進行訪問。 那麼靜態成員函數有特點呢? 1.靜態成員之間可以相互訪問,包括靜態成員函數訪問靜態數據成員和訪問靜態成員函數; 2.非靜態成員函數可以任意地訪問靜態成員函數和靜態數據成員; 3.靜態成員函數不能訪問非靜態成員函數和非靜態數據成員; 4.調用靜態成員函數,可以用成員訪問操作符(.)和(->)為一個類的對象或指向類對象的指針調用靜態成員函數,也可以用類名::函數名調用(因為他本來就是屬於類的,用類名調用很正常) 前三點其實是一點:靜態成員函數不能訪問非靜態(包括成員函數和數據成員),但是非靜態可以訪問靜態,有點暈嗎?沒關系,我給你個解釋, 因為靜態是屬於類的,它是不知道你創建了10個還是100個對象,所以它對你對象的函數或者數據是一無所知的,所以它沒辦法調用,而反過來,你創建的對象是對類一清二楚的(不然你怎麼從它那裡實例化呢),所以你是可以調用類函數和類成員的,就像不管GetSum是不是static,都可以調用static的s_sum一樣。