靜態的資料成員在記憶體中只佔乙份空間。每個物件都可以引用這個靜態資料成員。靜態資料成員的值對所有物件都是一樣的。如果改變它的值,則在各物件中這個資料成員的值都同時改變了。這樣可以節約空間,提高效率。
關於靜態資料成員的幾點說明:
1) 如果只宣告了類而未定義物件,則類的一般資料成員是不佔記憶體空間的,只有在定義物件時,才為物件的資料成員分配空間。但是靜態資料成員不屬於某乙個物件,在為物件所分配的空間中不包括靜態資料成員所佔的空間。靜態資料成員是在所有物件之外單獨開闢空間。只要在類中定義了靜態資料成員,即使不定義物件,也為靜態資料成員分配空間,它可以被引用。在乙個類中可以有乙個或多個靜態資料成員,所有的物件共享這些靜態資料成員,都可以引用它。
2) 對於靜態變數,如果在乙個函式中定義了靜態變數,在函式結束時該靜態變數並不釋放,仍然存在並保留其值。靜態資料成員也類似,它不隨物件的建立而分配空間,也不隨物件的撤銷而釋放(一般資料成員是在物件建立時分配空間,在物件撤銷時釋放)。靜態資料成員是在程式編譯時被分配空間的,到程式結束時才釋放空間。
3) 靜態資料成員可以初始化,但只能在類體外進行初始化。如
int box::height=10; //表示對box類中的資料成員初始化
其一般形式為:
資料型別類名::靜態資料成員名=初值;
不必在初始化語句中加static。
注意,不能用引數對靜態資料成員初始化。如在定義box類中這樣定義建構函式是錯誤的:
box(int h,int w,int
len):height(h) //錯誤,height是靜態資料成員
4) 靜態資料成員既可以通過物件名引用,也可以通過類名來引用。
5) 有了靜態資料成員,各物件之間的資料有了溝通的渠道,實現資料共享,因此可以不使用全域性變數。全域性變數破壞了封裝的原則,不符合物件導向程式的要求。但是也要注意公用靜態資料成員與全域性變數的不同,靜態資料成員的作用域只限於定義該類的作用域內(如果是在乙個函式中定義類,那麼其中靜態資料成員的作用域就是此函式內)。在此作用域內,可以通過類名和域運算子「::」引用靜態資料成員,而不論類物件是否存在。
與資料成員類似,成員函式也可以定義為靜態的,在類中宣告函式的前面加static就成了靜態成員函式。如
static
int volume( );
與靜態資料成員不同,靜態成員函式的作用不是為了物件之間的溝通,而是為了能處理靜態資料成員。
可以說,靜態成員函式與非靜態成員函式的根本區別是:非靜態成員函式有this指標,而靜態成員函式沒有this指標。由此決定了靜態成員函式不能訪問本類中的非靜態成員。
靜態成員函式可以直接引用本類中的靜態資料成員,因為靜態成員同樣是屬於類的,可以直接引用。在c++程式中,靜態成員函式主要用來訪問靜態資料成員,而不訪問非靜態成員。
1) 將普通函式宣告為友元函式
如果在本類以外的其他地方定義了乙個函式(這個函式可以是不屬於任何類的非成員函式,也可以是其他類的成員函式),在類體中用friend對其進行宣告,此函式就稱為本類的友元函式。友元函式可以訪問這個類中的私有成員。
...
class time
;...
void display(time& t) //這是友元函式,形參t是time類物件的引用
;class date //宣告date類
;...
void time::display(date &d) //display的作用是輸出年、月、日和時、分、秒
...int main( )
3) 乙個函式(包括普通函式和成員函式)可以被多個類宣告為「朋友」,這樣就可以引用多個類中的私有資料。
不僅可以將乙個函式宣告為乙個類的「朋友」,而且可以將乙個類(例如b類)宣告為另乙個類(例如a類)的「朋友」。這時b類就是a類的友元類。
友元類b中的所有函式都是a類的友元函式,可以訪問a類中的所有成員。在a類的定義體中用以下語句宣告b類為其友元類:
friend b;
宣告友元類的一般形式為:
friend 類名;
關於友元,有兩點需要說明:
template
//宣告乙個模板,虛擬型別名為numtype
class compare //類模板名為compare
numtype max( )
numtype min( )
;
使用模板類的方法是,必須用實際型別名去取代虛擬的型別,具體的做法是:
compare cmp(4,7);
上面列出的類模板中的成員函式是在類模板內定義的。這裡寫**片
如果改為在類模板外定義,不能用一般定義類成員函式的形式:
numtype compare::max( ) //不能這樣定義類模板中的成員函式
而應當寫成類模板的形式:
template numtype>
numtype compare
::max( )
歸納以上的介紹,可以這樣宣告和使用類模板:
1) 先寫出乙個實際的類。由於其語義明確,含義清楚,一般不會出錯。
2) 將此類中準備改變的型別名(如int要改變為float或char)改用乙個自己指定的虛擬型別名(如上例中的numtype)。
3) 在類宣告前面加入一行,格式為:
template 類模板名《實際型別名》 物件名;
類模板名《實際型別名》 物件名(實參表列);
5) 如果在類模板外定義成員函式,應寫成類模板形式:
template
函式型別 類模板名《虛擬型別引數》::成員函式名(函式形參表列)
關於類模板的幾點說明:
1) 類模板的型別引數可以有乙個或多個,每個型別前面都必須加class,如:
template t1,class
t2>
class
someclass
;
在定義物件時分別代入實際的型別名,如:
someclass obj;
2) 和使用類一樣,使用類模板時要注意其作用域,只能在其有效作用域內用它定義物件。
3) 模板可以有層次,乙個類模板可以作為基類,派生出派生模板類。
C 學習筆記 類和物件(1)
實體 客觀世界存在的某種事物,一杯茶,乙個人。每個實體都有屬性,其中,特徵稱為靜態屬性,功能稱為動態屬性。比如人的特徵,人的功能 物件 對實體進行抽象得到了物件。類 class 具有相同特徵與功能的物件集合。物件是類的例項化 instance 如果出現以下幾種情況,程式就會執行析構函式 如果在乙個函...
C 學習筆記 類和物件(下篇)
include using namespace std 初始化列表 class b private int a 4 char b 1 class a class d private int g void display private int year 4 int month 4 int day 4...
C 學習(八) 類和物件(三)
include include using namespace std 系統提供的拷貝函式,只會做簡單的值拷貝 如果類中有屬性開闢到堆區,那麼在釋放的時候,由於淺拷貝問題導致堆區內容會重複釋放程式down掉 利用深拷貝 解決淺拷貝帶來的問題 class persion persion const p...