標籤:c++

1類的聲明和對象的定義

類和對象的關係
類是對象的抽象,而對象是類的具體實例。類是抽象的,不佔用內存,而對象是具體的,佔用存儲空間。類是用於創建對象的藍圖,它是一個定義包括在特定類型的對象中的方法和變數的軟體模板。
定義對象的方法
1.先聲明類類型,然後再定義對象
舉例:Student stud1,stud2;  //Student是已經聲明的類類型
2.在聲明類類型的同時定義對象
class Student
//聲明類類型
{public :
//先聲明公用部分
void display( )
{cout<<″num:″<<num<<endl;
cout<<″name:″<<name<<endl;
cout<<″sex:″<<sex<<endl;}
private :
//后聲明私有部分
int num;
char name[20];
char sex;
}stud1,stud2;//定義了兩個Student類的對象
在定義Student類的同時,定義了兩個Student 類的對象。
3.不出現類名,直接定義對象
class //無類名
{private : //聲明以下部分為私有的
public : //聲明以下部分為公用的
}stud1,stud2;//定義了兩個無類名的類對象
直接定義對象,在C++中是合法的、允許的,但卻很少用,也不提倡用。在實際的程序開發中,一般都採用上面3種方法中的第1種方法。在小型程序中或所聲明的類只用於本程序時,也可以用第2種方法。在定義一個對象時,編譯系統會為這個對象分配存儲空間,以存放對象中的成員。
成員函數的性質
類的成員函數(簡稱類函數)是函數的一種,它的用法和作用和第4章介紹過的函數基本上是一樣的,它也有返回值和函數類型,
它與一般函數的區別只是:
它是屬於一個類的成員,出現在類體中。
它可以被指定為private(私有的)、public (公用的)或protected(受保護的)。
在使用類函數時,要注意調用它的許可權(它能否被調用)以及它的作用域(函數能使用什麼範圍中的數據和函數)。
例如私有的成員函數只能被本類中的其它成員函數所調用,而不能被類外調用。
成員函數可以訪問本類中任何成員(包括私有的和公用的),可以引用在本作用域中有效的數據。
一般的做法是將需要被外界調用的成員函數指定為public,它們是類的對外介面。
但應注意,並非要求把所有成員函數都指定為public。有的函數並不是準備為外界調用的,而是為本類中的成員函數所調用的,就應該將它們指定為private。
這種函數的作用是支持其它函數的操作,是類中其它成員的工具函數(utility function),類外用戶不能調用這些私有的工具函數。
類的成員函數是類體中十分重要的部分。如果一個類中不包含成員函數,就等同於C語言中的結構體了,體現不出類在面向對象程序設計中的作用。
inline 成員函數
在類體中定義的成員函數的規模一般都很小,而系統調用函數的過程所花費的時間開銷相對是比較大的。調用一個函數的時間開銷遠遠大於小規模函數體中全部語句的執行時間。
為了減少時間開銷,如果在類體中定義的成員函數中不包括循環等控制結構,C++系統會自動將它們作為內置(inline )函數來處理。
也就是說,在程序調用這些成員函數時,並不是真正地執行函數的調用過程(如保留返回地址等處理),而是把函數代碼嵌入程序的調用點。
這樣可以大大減少調用成員函數的時間開銷。C++要求對一般的內置函數要用關鍵字inline聲明,但對類內定義的成員函數,可以省略inline,因為這些成員函數已被隱含地指定為內置函數。如
class Student
{public :
void display( )
{cout<<″num:″<<num<<endl;cout<<″name:″
<<name<<endl;cout<<″sex:″<<sex<<endl;}
private :
int num;
string name;
char sex;
};
其中第3行
void display( ) 也可以寫成
inline void display( )
將display函數顯式地聲明為內置函數。
以上兩種寫法是等效的。對在類體內定義的函數,一般都省寫inline。
應該注意的是: 如果成員函數不在類體內定義,而在類體外定義,系統並不把它默認為內置(inline )函數,調用這些成員函數的過程和調用一般函數的過程是相同的。如果想將這些成員函數指定為內置函數,應當用inline作顯式聲明。如
class Student
{
public : inline void display( );//聲明此成員函數為內置函數
private :
int num;
string name;
char sex;
};
inline void Student∷display( ) // 在類外定義display函數為內置函數
{cout<<″num:″<<num<<endl;cout<<″name:″<<name<<endl;cout<<″sex:″<<sex<<endl;}
在函數的聲明或函數的定義兩者之一作inline聲明即可。
值得注意的是: 如果在類體外定義inline函數,則必須將類定義和成員函數的定義都放在同一個頭文件中(或者寫在同一個源文件中),否則編譯時無法進行置換(將函數代碼的拷貝嵌入到函數調用點)。
但是這樣做,不利於類的介面與類的實現分離,不利於信息隱蔽。雖然程序的執行效率提高了,但從軟體工程質量的角度來看,這樣做並不是好的辦法。
只有在類外定義的成員函數規模很小而調用頻率較高時,才將此成員函數指定為內置函數。
通過對象名和成員運算符訪問對象中的成員
例如在程序中可以寫出以下語句:
stud1.num=1001;//假設num已定義為公用的整型數據成員
表示將整數1001賦給對象stud1中的數據成員num。
其中「.」是成員運算符,用來對成員進行限定,指明所訪問的是哪一個對象中的成員。
注意不能只寫成員名而忽略對象名。
訪問對象中成員的一般形式為
對象名.成員名
不僅可以在類外引用對象的公用數據成員,而且還可以調用對象的公用成員函數,但同樣必須指出對象名,如
stud1.display( );//正確,調用對象stud1的公用成員函數
display( );//錯誤,沒有指明是哪一個對象的display函數
由於沒有指明對象名,編譯時把display作為普通函數處理。
應該注意所訪問的成員是公用的(public )還是私有的(private )。只能訪問public成員,而不能訪問private成員,如果已定義num為私有數據成員,下面的語句是錯誤的:
stud1.num=10101;//num是私有數據成員,不能被外界引用
在類外只能調用公用的成員函數。在一個類中應當至少有一個公用的成員函數,作為對外的介面,否則就無法對對象進行任何操作。
通過對象的引用變數來訪問對象中的成員
如果為一個對象定義了一個引用變數,它們是共占同一段存儲單元的,實際上它們是同一個對象,只是用不同的名字表示而已。
因此完全可以通過引用變數來訪問對象中的成員。
如果已聲明了Time類,並有以下定義語句:
Time t1; //定義對象t1
Time &t2=t1;//定義Time類引用變數t2,並使之初始化為t1
cout<<t2.hour;//輸出對象t1中的成員hour
由於t2與t1共占同一段存儲單元(即t2是t1的別名),因此t2.hour就是t1.hour。

2類和對象的簡單應用舉例

例2
引用多個對象的成員。
(1) 程序(a)
#include <iostream>
using namespace std;
class Time
{public :
int hour;
int minute;
int sec;
};
int main( )
{Time t1;//定義對象t1
cin>>t1.hour;//向t1的數據成員輸入數據
cin>>t1.minute;
cin>>t1.sec;
cout<<t1.hour<<″:″<<t1.minute<<″:″<<t1.sec<<endl;//輸出t1中數據成員的值
Time t2;//定義對象t2
cin>>t2.hour;//向t2的數據成員輸入數據
cin>>t2.minute;
cin>>t2.sec;
cout<<t2.hour<<″:″<<t2.minute<<″:″<<t2.sec<<endl;//輸出t2中數據成員的值
return 0;
}
運行情況如下:
1032 43↙
10:32:43
22 32 43↙
22:32:43
程序是清晰易懂的,但是在主函數中對不同的對象一一寫出有關操作,會使程序冗長。為了
解決這個問題,可以使用函數來進行輸入和輸出。見程序(b)。
(2) 程序(b)
#include <iostream>
using namespace std;
class Time
{public :
int hour;
int minute;
int sec;
};
int main( )
{
void set_time(Time&);//函數聲明
void show_time(Time&);//函數聲明
Time t1;//定義t1為Time類對象
set_time(t1);//調用set_time函數,向t1對象中的數據成員輸入數據
show_time(t1);//調用show_time函數,輸出t1對象中的數據
Time t2;//定義t2為Time類對象
set_time(t2);//調用set_time函數,向t2對象中的數據成員輸入數據
show_time(t2);//調用show_time函數,輸出t2對象中的數據
return 0;
}
void set_time(Time& t) //定義函數set_time,形參t是引用變數
{
cin>>t.hour;//輸入設定的時間
cin>>t.minute;
cin>>t.sec;
}
void show_time(Time& t) //定義函數show_time,形參t是引用變數
{
cout<<t.hour<<″:″<<t.minute<<″:″<<t.sec<<endl;//輸出對象中的數據
}
運行情況與程序(a)相同。
(3) 程序(c)
可以對上面的程序作一些修改,數據成員的值不再由鍵盤輸入,而在調用函數時由實參給出,並在函數中使用默認參數。將程序(b)第8行以下部分改為
int main( )
{
void set_time(Time&,int hour=0,int
minute=0,int sec=0);//函數聲明
void show_time(Time&);//函數聲明
Time t1;
set_time(t1,12,23,34);//通過實參傳遞時、分、秒的值
show_time(t1);
Time t2;
set_time(t2);//使用默認的時、分、秒的值
show_time(t2);
return 0;
}
void set_time(Time& t,int hour,int minute,int sec)
{
t.hour=hour;
t.minute=minute;
t.sec=sec;
}
void show_time(Time& t)
{
cout<<t.hour<<″:″<<t.minute<<″:″<<t.sec<<endl;
}
程序運行時的輸出為
12:23:34 (t1中的時、分、秒)
0:0:0 (t2中的時、分、秒)
以上兩個程序中定義的類都只有數據成員,沒有成員函數,這顯然沒有體現出使用類的優越性。在下面的例子中,類體中就包含了成員函數。
例4
找出一個整型數組中的元素的最大值。這個問題可以不用類的方法來解決,現在用類來處理,讀者可以比較不同方法的特點。
#include <iostream>
using namespace std;
class Array_max //聲明類
{public : //以下3行為成員函數原型聲明
void set_value( ); //對數組元素設置值
void max_value( ); //找出數組中的最大元素
void show_value( ); //輸出最大值
private :
int array[10]; //整型數組
int max; //max用來存放最大值
};
void Array_max∷set_value( ) //成員函數定義,向數組元素輸入數值
{ int i;
for (i=0;i<10;i++)
cin>> array[i];
}
void Array_max∷max_value( ) //成員函數定義,找數組元素中的最大值
{int i;
max=array[0];
for (i=1;i<10;i++)
if(array[i]> max) max=array[i];
}
void Array_max∷show_value( ) //成員函數定義,輸出最大值
{cout<< ″max=″<< max;}
int main( )
{Array_max arrmax; //定義對象arrmax
arrmax.set_value( ); //調用arrmax的set_value函數,向數組元素輸入數值
arrmax.max_value( ); //調用arrmax的max_value函數,找出數組元素中的最大值
arrmax.show_value( ); //調用arrmax的show_value函數,輸出數組元素中的最大值
return 0;
}
運行結果如下:
12 12 39 -34 17 134 045 -91 76↙ (輸入10個元素的值)
max=134 (輸入10個元素中的最大值)
請注意成員函數定義與調用成員函數的關係,定義成員函數只是設計了一組操作代碼,並未實際執行,只有在被調用時才真正地執行這一組操作。
可以看出: 主函數很簡單,語句很少,只是調用有關對象的成員函數,去完成相應的操作。
在大多數情況下,主函數中甚至不出現控制結構(判斷結構和循環結構),而在成員函數中使用控制結構。
在面向對象的程序設計中,最關鍵的工作是類的設計。所有的數據和對數據的操作都體現在類中。
只要把類定義好,編寫程序的工作就顯得很簡單了。
上一篇[特殊矩陣]  

相關評論

同義詞:暫無同義詞