? ?當將類的某個數據成員聲明為static時,該靜態數據成員只能被定義一次,而且要被同類的所有對象共享。各個對象都擁有類中每一個普通數據成員的副本,但靜態數據成員只有一個實例存在,與定義了多少類對象無關。靜態方法就是與該類相關的,是類的一種行為,而不是與該類的實例對象相關。
?? ?靜態數據成員的用途之一是統計有多少個對象實際存在。
?? ?靜態數據成員不能在類中初始化,實際上類定義只是在描述對象的藍圖,在其中指定初值是不允許的。也不能在類的構造函數中初始化該成員,因為靜態數據成員為類的各個對象共享,否則每次創建一個類的對象則靜態數據成員都要被重新初始化。
?? ?靜態成員不可在類體內進行賦值,因為它是被所有該類的對象所共享的。你在一個對象里給它賦值,其他對象里的該成員也會發生變化。為了避免混亂,所以不可在類體內進行賦值。
?? ?靜態成員的值對所有的對象是一樣的。靜態成員可以被初始化,但只能在類體外進行初始化。
?? ?一般形式:
?? ?數據類型類名 :: 靜態數據成員名=初值
?? ?注意:不能用參數初始化表對靜態成員初始化。一般系統缺省初始為0。
?? ?靜態成員是類所有的對象的共享的成員,而不是某個對象的成員。它在對象中不占用存儲空間,這個屬性為整個類所共有,不屬于任何一個具體對象。所以靜態成員不能在類的內部初始化,比如聲明一個學生類,其中一個成員為學生總數,則這個變量就應當聲明為靜態變量,應該根據實際需求來設置成員變量。
#include "iostream"
using namespace std;
class test
{
private:
?? ? int x;
?? ? int y;
public:
?? ? static int num;
?? ? static int Getnum()
?? ? {
?? ? ? ? ?x+=5; ? //這行代碼是錯誤的,靜態成員函數不能調用非靜態數據成員,要通過類的對象來調用。
?? ? ? ? ?num+=15;
?? ? ? ? ?return num;
?? ? }
};
int test::num = 10;
int main(void)
{
?? ? test a;
?? ? cout<<test::num<<endl; ? ? ? ?//10
?? ? test::num = 20;
?? ? cout<<test::num<<endl; ? ? ? ?//20
?? ? cout<<test::Getnum()<<endl; ??//35
?? ? cout<<a.Getnum()<<endl; ? ? ??//50
?? ? system("pause");
?? ? return 0;
}
?? ?通過上例可知:??x+=5; ? // 這行代碼是錯誤的
?? ?靜態函數成員必須通過對象名來訪問非靜態數據成員。
?? ?另外,靜態成員函數在類外實現時候無須加static關鍵字,否則是錯誤的。
?? ?若在類的體外來實現上述的那個靜態成員函數,不能加static關鍵字,這樣寫就可以了:
?? ? int test::Getnum()
?? ? {
?? ? ? .........
?? ? }
1、static成員的所有者是類本身和對象,但是多有對象擁有一樣的靜態成員。從而在定義對象是不能通過構造函數對其進行初始化。
2、靜態成員不能在類定義里邊初始化,只能在class body外初始化。
3、靜態成員仍然遵循public,private,protected訪問準則。
4、靜態成員函數沒有this指針,它不能返回非靜態成員,因為除了對象會調用它外,類本身也可以調用。
?
靜態成員函數可以直接訪問該類的靜態數據和函數成員,而訪問非靜態數據成員必須通過參數傳遞的方式得到一個對象名,然后通過對象名來訪問。
class Myclass
{
private:
??????? int a,b,c;
??????? static int Sum;??? //聲明靜態數據成員
public:
??????? Myclass(int a,int b,int c);
??????? void GetSum();
};
int Myclass::Sum=0;?????? //定義并初始化靜態數據成員
Myclass::Myclass(int a,int b,int c)
{
??????? this->a=a;
??????? this->b=b;
??????? this->c=c;
??????? Sum+=a+b+c;
}
void Myclass::GetSum()
{
??????? cout <<"Sum=" <<Sum <<endl;
}
int main(void)
{
??????? Myclass me(10,20,30);
??????? me.GetSum();
??????? system("pause");
??????? return 0;
}
?
?
?
由上例可知,非靜態成員函數可以任意地訪問靜態成員函數和靜態數據成員。
非靜態成員函數Myclass(int a,int b,int c)和GetSum()都訪問了靜態數據成員Sum。
靜態成員函數不能訪問非靜態成員函數和非靜態數據成員。
?
關于靜態成員函數,可以總結為以下幾點:
出現在類體外的函數定義不能指定關鍵字static;
靜態成員之間可以相互訪問,包括靜態成員函數訪問靜態數據成員和訪問靜態成員函數;
非靜態成員函數可以任意地訪問靜態成員函數和靜態數據成員;
靜態成員函數不能訪問非靜態成員函數和非靜態數據成員;
由于沒有this指針的額外開銷,因此靜態成員函數與類的全局函數相比速度上會有少許的增長;
調用靜態成員函數,可以用成員訪問操作符(.)和(->)為一個類的對象或指向類對象的指針調用靜態成員函數,
當同一類的所有對象使用一個量時,對于這個共用的量,可以用靜態數據成員變量,這個變量對于同一類的所有的對象都取相同的值。靜態成員變量只能被靜態成員函數調用。靜態成員函數也是由同一類中的所有對象共用。只能調用靜態成員變量和靜態成員函數。
首先,函數不是對象,它代表的是一段代碼,位于代碼段,而不是位于靜態存儲區——靜態存儲區是數據區的一種,用來存放在程序中定義的靜態對象。
對類的靜態和非靜態函數的不同的調用要求決定了它們在使用上的方便程度:非靜態成員函數要通過對象調用,所以要求首先建立一個對象;而靜態成員函數可不建立對象就可以被使用。因此,與類的非靜態數據成員無關的成員函數,雖然可以被定義為非靜態函數,但是如果定義為靜態函數的話在使用上會更加方便。
另外,如果類的成員函數想作為回調函數來使用,一般情況下只能將它定義為靜態成員才行
C++會區分兩種類型的成員函數:靜態成員函數和非靜態成員函數。這兩者之間的一個重大區別是,靜態成員函數不接受隱含的this自變量。所以,它就無法訪問自己類的非靜態成員。
左例中分別聲明了成員函數void add(),成員變量int a,和靜態成員函數 static void staticfunc(),靜態成員變量 static int sa.
在staticfunc()的定義中,由于沒有this指針,所以無法訪問普通成員變量和成員函數.
?
?
?
網絡上有很多關于解決靜態成員函數訪問普通成員變量的方法,總結如下:
http://www.360doc.com/content/10/1201/22/963301_74198801.shtml