最近一直看c++相關的項目,但總是會被c++類中的靜態成員變量與靜態成員函數的理解感覺很是模糊,不明白為什么類中要是用靜態成員變量.於是在網上搜集了一些資料,自己再稍微總結下。
靜態成員的概念:
靜態類中的成員加入static修飾符,即是靜態成員.可以直接使用類名+靜態成員名訪問此靜態成員,因為靜態成員先於類的聲明而存在於內存,也可以根據類聲明的對象來訪問.而非靜態成員必須實例化之后才會分配內存.
非靜態成員的概念:
所有沒有加static的成員都是非靜態成員.而類被實例化后,可以通過實例化的類名進行訪問.非靜態成員的生存期決定於該類的生存期.而靜態成員不存在生產期的問題,因為它始終駐留在內存.
分兩個方面來總結,面向過程與面向對象.
一:面向過程中的static關鍵字
1.靜態全局變量
定義全局變量前,加上關鍵字static,該變量就被定義成了一個靜態全局變量.
特點:
- 該變量在全局數據區分配內存.
- 初始化:如果不是顯示初始化,那么將被隱式初始化為0.
- 訪變量只在本文件可見,即應該為定義之處開始到本文件結束.
程序在內存中一般分為四個區域:
- 代碼區
- 全局數據區
- 堆區
- 棧區
一般程序由new產生的動態數據放在堆區,函數內部的自動變量放在棧區.自動變量一般會隨着函數的退出而釋放空間,靜態數據(即使是函數內部的靜態局部變量)都存放在全局數據區.因此它們並不會隨着函數的退出而釋放空間.
static int n;//定義靜態全局變量
改為: int n;//定義全局變量
區別:
靜態全局變量不能被其他文件所用.因而其他文件可以定義相同名字的變量,而不會發生沖突.
例子:
//Example //File 1
#include <iostream>
void fn(); static int n;//定義靜態全局變量(只能在本文件中使用)
void main(){ n=20; cout<<n<<endl; fn(); } //File 2
#include <iostream>
extern int n;(可在別的文件中引用這個變量) void fn(){ n++; cout<<n<<endl; }//編譯並運行Example,就會發現上述代碼分別通過編譯,但Link時會出錯.
如果將static int n改為 :int n; 再次編譯運行程序,就不會出錯.
2.靜態局部變量
在局部變量前加上static 關鍵字,就定義了靜態局部變量.
特點:
A.該變量在全局數據區分配內存.
B.初始化時:如果不是顯示初始化,那么將隱式初始化為0.
C.它始終駐留在全局數據區,直到程序結束.但其作用域為局部作用域.當定義它的函數或語句塊時,其作用域隨之結束.
3.靜態函數:在函數的返回類型前加上static關鍵字.
特點:靜態函數與普通函數不同,它只能在聲明它的文件當中可見,不能被其他文件可用.
二:面向對象的static關鍵字
1.靜態數據成員
在類中數據成員的聲明前加上static,該成員是類的靜態數據成員.
例子:
//example 2
#include <iostream>
class MyClass{ public: MyClass(int a,int b,int c); void GetSum(); private: int a,b,c; static int sum;//聲明靜態數據成員
}; int MyClass::sum=0;//定義並初始化靜態數據成員
特點:
對於非靜態數據成員,每個類對象都有自己的拷貝.而靜態數據成員被當做是類的成員,無論這個類被定義了多少個,靜態數據成員都只有一份拷貝,為該類型的所有對象所共享(包括其派生類).所以,靜態數據成員的值對每個對象都是一樣的,它的值可以更新.
因為靜態數據成員在全局數據區分配內存,屬於本類的所有對象共享,所以它不屬於特定的類對象,在沒有產生類對象前就可以使用.
2.靜態成員函數
與普通的成員函數相比,靜態成員函數由於不是與任何的對象相聯系,因此它不具有this指針.從這個意義上來說,它無法訪問屬於類對象的非靜態數據成員,也無法訪問非靜態成員函數,只能調用其他的靜態成員函數.