C++ 入門指南 4.01
單元 10 - 類別
類別 (class) 用來設計自己需要的物件 (object) ,這是說,類別是物件的藍圖。 C++ 中設計類別使用關鍵字 (keyword) class ,後面接大括弧宣告 (declare) 類別的成員 (member)
成員可以是資料 (data) 、函數 (function) 與建構函數 (constructor) ,資料其實就是專屬於類別的變數 (variable) ,我們在這裡沿用 C++ 的習慣稱之為資料成員 (data member) ,同樣的,函數也是專屬於類別的,稱之為成員函數 (member function) ,至於建構函數屬於特別的成員函數,用來建立該類別物件的專屬函數。
因為建構函數用來建立物件,所以建構函數沒有回傳值 (return value) ,或著可以這麼想像,建構函數預設回傳物件自己本身,因此無須宣告回傳值。
另外,類別定義必須利用存取標籤 (access label) public 或 private 將成員的權限歸類,屬於 public 的成員可以在程式中的任何地方存取, private 則只能在同個類別裡。
為什麼要對存取權限歸類呢?這是因為物件導向程式設計允許後續定義的類別繼承 (inherit) 之前定義類別的特性,這樣的機制使 public 成員會被繼承,而 private 不能被繼承。還有另一個存取標籤 protected ,不過這不在我們目前的討論範圍。
我們舉一例如下
#include <iostream> using namespace std; // 宣告類別 class Demo { // 宣告 public 成員 public: int a; int b; int DoSomething(); }; // 實作 Demo 的 DoSomething() 成員函數 int Demo::DoSomething() { return a + b; } // 程式執行的 main() int main(void) { // 宣告並建立 Demo 型態的物件 t Demo t; t.a = 11; // 直接設定成員變數值 t.b = 22; cout << endl; // 呼叫並印出 DoSomething() 的回傳值 cout << t.DoSomething() << endl; cout << endl; return 0; } /* 《程式語言教學誌》的範例程式 http://kaiching.org/ 檔名:class_demo.cxx 功能:示範定義類別 作者:張凱慶 */
此例中的 Demo 類別宣告三個 public 成員, a 、 b 為成員變數, DoSomething() 為成員函數,記得, class 大括弧的最後要加上分號
// 宣告類別 class Demo { // 宣告 public 成員 public: int a; int b; int DoSomething(); };
底下為實作 Demo 類別中的 DoSomething() 成員函數
// 實作 Demo 的 DoSomething() 成員函數 int Demo::DoSomething() { return a + b; }
DoSomething() 的工作很簡單,就是回傳兩個成員變數 a 與 b 的相加值。這裡須注意定義成員函數時,必須在成員函數名稱前加上所屬類別名稱接兩個冒號
int Demo::DoSomething() {
這是標明 DoSomething() 是屬於 Demo 類別的,連續兩個冒號 :: 為作用域運算子 (scope operator) 。沒有這樣寫的話,編譯器 (compiler) 會把 DoSomething() 當成普通的函數處理。
也可以直接把成員函數的實作直接寫在宣告的地方,我們建議分開寫,因為小程式可能看起來沒差,大型程式在習慣上會把宣告放在標頭檔 (header file) 。
下面的 main() 直接用小數點運算子設定 a 與 b ,然後印出 DoSomething() 的回傳值
// 程式執行的 main() int main(void) { // 宣告並建立 Demo 型態的物件 t Demo t; t.a = 11; // 直接設定成員變數值 t.b = 22; cout << endl; // 呼叫並印出 DoSomething() 的回傳值 cout << t.DoSomething() << endl; cout << endl; return 0; }
編譯執行看看結果吧
這個例子我們只用到 public ,接下來我們要繼續介紹 private ,將資料有效的封裝 (encapsulation) 在物件裡。
中英文術語對照 | |
---|---|
存取標籤 | access label |
類別 | class |
編譯器 | compiler |
建構函數 | constructor |
資料 | data |
資料成員 | data member |
宣告 | declare |
封裝 | encapsulation |
函數 | function |
標頭檔 | header file |
繼承 | inherit |
關鍵字 | keyword |
成員 | member |
成員函數 | member function |
物件 | object |
回傳值 | return value |
作用域運算子 | scope operator |
變數 | variable |
重點整理 |
---|
1. 類別是物件的藍圖,每一個類別都可以定義資料成員及成員函數,宣告類別使用關鍵字 class ,每個成員都要用存取標籤分類,大括弧的最後要加上分號。 |
2. 建構函數屬於特別的成員函數,用來建立該類別的物件。 |
3. 成員函數的實作通常會放在類別宣告外,需要標上類別名稱與作用域運算子表示屬於哪個類別。 |
4. 宣告建立類別的物件(變數)後,可用小數點運算子指派數值給 public 的成員變數,也可用小數點運算子呼叫成員函數。 |
問題與討論 |
---|
1. 為什麼類別要有專屬的變數及函數?想一想,這跟物件的意涵有什麼關聯? |
2. 成員函數跟一般的函數有什麼不同?資料成員跟一般的變數又有什麼不同? |
3. 除了建構函數、成員函數及資料成員之外,類別中還有其他種類的成員嗎? |
4. 為什麼要有建構函數?建構函數的用途是什麼? |
5. 為什麼成員函數的實作要放在類別宣告之外? |
練習 |
---|
1. 寫一個程式 exercise1001.cxx ,裡頭設計一個類別 IntegerDemo , IntegerDemo 有一個 int 的成員變數 value ,另有一個沒有回傳值的成員函數 Add() , Add() 有一個 int 參數,呼叫 Add() 時會把參數與 value 相加,結果儲存在 value ,執行部分先將 value 設定為 25 ,再呼叫 Add() 以 24 當參數。 參考程式碼 |
2. 承上題,另寫一個程式 exercise1002.cxx ,改成由使用者輸入兩個整數。 參考程式碼 |
3. 承上題,另寫一個程式 exercise1003.cxx ,加入成員函數 Subtract() , Subtract() 沒有回傳值,另外需要一個 int 參數,同樣呼叫 Subtract() 是將 value 減去參數值,最後結果儲存在 value 。 參考程式碼 |
4. 承上題,另寫一個程式 exercise1004.cxx ,繼續擴充 IntegerDemo ,加入乘法的成員函數 Multiply() 。 參考程式碼 |
5. 承上題,另寫一個程式 exercise1005.cxx ,繼續擴充 IntegerDemo ,加入除法的成員函數 Divide() 。 參考程式碼 |
6. 承上題,另寫一個程式 exercise1006.cxx ,繼續擴充 IntegerDemo ,加入取餘數的成員函數 Modulo() 。 參考程式碼 |
7. 寫一個程式 exercise1007.cxx ,仿照 IntegerDemo 設計 FactorialDemo ,利用成員函數 Compute() 計算階層值,參數 n 為第幾個階層數,印出使用者,結果儲存在成員變數 value 。 參考程式碼 |
8. 寫一個程式 exercise1008.cxx ,仿照 IntegerDemo 設計 FibonacciDemo ,利用成員函數 Compute() 計算費氏數列,參數 n 為第幾個階層數,印出使用者,結果儲存在成員變數 value 。 參考程式碼 |
9. 寫一個程式 exercise1009.cxx ,設計一個平面座標類別 Point ,至少要有兩個成員變數儲存平面座標 x 與 y ,以及計算距離的成員函數 Distance() ,兩點距離為 x 、 y 座標的差值相加。 參考程式碼 |
10. 寫一個程式 exercise1010.cxx ,設計一個猜數字遊戲類別 Guess ,至少要有ㄧ個字串型態的成員變數 answer 儲存答案,先設定 answer 後,再印出 answer 值。 參考程式碼 |
11. 寫一個程式 exercise1011.cxx ,設計一個記錄成員的類別 Member ,至少要有兩個成員變數,一個整數型態 id 儲存成員的編號,另一個字串型態 name 儲存成員的暱稱,設定 id 為 0 以及 name 為 "Alice" ,然後印出兩個成員變數。 參考程式碼 |
12. 寫一個程式 exercise1012.cxx ,設計一個載入文字的類別 Text ,至少要有ㄧ個字串型態的成員變數 content 儲存載入的文字,設定 content 為 "demo" 然後印出來。 參考程式碼 |
13. 寫一個程式 exercise1013.cxx ,設計一個乒乓球的類別 Ball ,至少要有ㄧ個 Point 型態成員變數 p 儲存球的座標,把 p 設定為原點然後印出來。 參考程式碼 |
14. 寫一個程式 exercise1014.cxx ,設計一個控制場景的類別 Scene ,至少要有兩個成員變數,一個整數型態 id 儲存場景的編號,另一個字串型態 text 儲存場景的描述文字,將 id 設定為 0 , text 設定為 "demo" ,然後印出來。 參考程式碼 |
15. 寫一個程式 exercise1015.cxx ,設計一個遊戲的類別 Game ,至少要用 Ball 或 Guess 型態的成員變數,以及成員函數 Run() ,執行部分放在 Run() ,使遊戲在 Run() 中運作。 參考程式碼 |
相關教學影片
- 類別 ⇨ YouTube 頁面連結
- 封裝 ⇨ YouTube 頁面連結
- static 、 const 與 mutable 成員 ⇨ YouTube 頁面連結
- 巢狀類別 ⇨ YouTube 頁面連結
- Copy 建構函數 ⇨ YouTube 頁面連結
- 多載運算子 ⇨ YouTube 頁面連結
- 繼承 ⇨ YouTube 頁面連結
- 多型 ⇨ YouTube 頁面連結