在沒有講述本章內容之前假如我們想要在一個范圍內共享某一個數據,那麼我們會設立全局對象,但面向對象的程序是由對象構成的,我們如何才能在類范圍內共享數據呢?
這個問題便是本章的重點:
<!-- frame contents -->
<!-- /frame contents -->
聲明為static的類成員或者成員函數便能在類的范圍內共同享,我們把這樣的成員稱做靜態成員和靜態成員函數。
下面我們用幾個實例來說明這個問題,類的成員需要保護,通常情況下為了不違反類的封裝特性,我們是把類成員設置為protected(保護狀態)的,但是我們為了簡化代碼,使要說明的問題更為直觀,更輕易理解,我們在此處都設置為public。
以下程序我們來做一個模擬訪問的例子,在程序中,每建立一個對象我們設置的類靜態成員變自動加一,代碼如下:#include <iostream>
using namespace std;
class Internet
{
public:
Internet(char *name,char *address)
{
strcpy(Internet::name,name);
strcpy(Internet::address,address);
count++;
}
static void Internet::Sc()//靜態成員函數
{
cout<<count<<endl;
}
Internet &Rq();
public:
char name[20];
char address[20];
static int count;//這裡假如寫成static int count=0;就是錯誤的
};
Internet& Internet::Rq()//返回引用的成員函數
{
return *this;
}
int Internet::count = 0;//靜態成員的初始化
void vist()
{
Internet a1("中國軟件開發實驗室","www.cndev-lab.com");
Internet a2("中國軟件開發實驗室","www.cndev-lab.com");
}
void fn(Internet &s)
{
cout<<s.Rq().count;
}
void main()
{
cout<<Internet::count<<endl;//靜態成員值的輸出
vist();
Internet::Sc();//靜態成員函數的調用
Internet b("中國軟件開發實驗室","www.cndev-lab.com");
Internet::Sc();
fn(b);
cin.get();
} 上面代碼我們用了幾種常用的方式建立對象,當建立新對象並調用其構造函數的時候,靜態成員cout便運行加1操作,靜態成員的初始化應該在主函數調用之前,並且不能在類的聲明中出現,通過運行過程的觀察我們發現,靜態成員count的狀態並不會隨著一個新的對象的新建而重新定義,盡而我們了解到類的靜態成員是屬於類的而不是屬於哪一個對象的,所以靜態成員的使用應該是類名稱加域區分符加成員名稱的,在上面的代碼中就是Internet::count,雖然我們仍然可以使用對象名加點操作符號加成員名稱的方式使用,但是不推薦的,靜態態類成員的特性就是屬於類而不專屬於某一個對象。
更多內容請看C/C++技術專題專題,或
靜態成員函數的特性類似於靜態成員的使用,同樣與對象無關,調用方法為類名稱加域區分符加成員函數名稱,在上面的代碼中就是Internet::Sc();,靜態成員函數由於與對象無關系,
<!-- frame contents -->
<!-- /frame contents -->
所以在其中是不能對類的普通成員進行直接操作的。
假如上面的 static void Internet::Sc()修改成為:static void Internet::Sc()//靜態成員函數
{
cout<<name<<endl;//錯誤
cout<<count<<endl;
} 靜態成員函數與普通成員函數的差別就在於缺少this指針,沒有這個this指針自然也就無從知道name是哪一個對象的成員了。 根據類靜態成員的特性我們可以簡單歸納出幾點,靜態成員的使用范圍:
1.用來保存對象的個數。
2.作為一個標記,標記一些動作是否發生,比如:文件的打開狀態,打印機的使用狀態,等等。
3.存儲鏈表的第一個或者最後一個成員的內存地址。
為了做一些必要的練習,深入的把握靜態對象的存在的意義,我們以前面的結構體的教程為基礎,用類的方式描述一個線性鏈表,用於存儲若干學生的姓名,代碼如下:#include <iostream>
using namespace std;
class Student
{
public:
Student (char *name);
~Student();
public:
char name[30];
Student *next;
static Student *point;
};
Student::Student (char *name)
{
strcpy(Student::name,name);
this->next=point;
point=this;
}
Student::~Student ()//析構過程就是節點的脫離過程
{
cout<<"析構:"<<name<<endl;
if(point==this)
{
point=this->next;
cin.get();
return;
}
for(Student *ps=point;ps;ps=ps->next)
{
if(ps->next==this)
{
cout<<ps->next<<""<<this->next<<endl;
ps->next=next;//=next也可以寫成this->next;
cin.get();
return;
}
}
cin.get();
}
Student* Student::point=NULL;
void main()
{
Student *c = new Student("marry");
Student a("colin");
Student b("jamesji");
delete c;
Student *fp=Student::point;
while(fp!=NULL)
{
cout<<fp->name<<endl;
fp=fp->next;
}
cin.get();
} 從上面的代碼來看,原來單純結構化編程需要的一個鏈表進入全局指針在這裡被類的靜態成員指針所替代(類的靜態成員完全可以替代全局變量),這個例子的理解重點主要是要注重觀察類成員的析構順序,通過對析構順序的理解,使用析構函數來進行節點的脫鏈操作。
更多內容請看C/C++技術專題專題,或