C++ 入門指南 V2.00 - 單元 10 - 類別




類別 (class) 用來設計自己需要的物件 (object) ,這是說,類別是物件的藍圖。 C++ 中設計類別使用關鍵字 (keyword) class ,後面接大括弧宣告 (declare) 類別的成員 (member)



成員可以是資料 (data) 、函數 (function) 與建構函數 (constructor) ,資料其實就是專屬於類別的變數 (variable) ,我們在這裡沿用 C++ 的習慣稱之為資料成員 (data member) ,同樣的,函數也是專屬於類別的,稱之為成員函數 (member function) ,至於建構函數屬於特別的成員函數,用來建立該類別物件的專屬函數。


因為建構函數用來建立物件,所以建構函數沒有回傳值 (return value) ,或著可以這麼想像,建構函數預設回傳物件自己本身,因此無須宣告回傳值。

另外,類別定義必須利用存取標籤 (accsee label) publicprivate 將成員的權限歸類,屬於 public 的成員可以在程式中的任何地方存取, private 則只能在同個類別裡。


為什麼要對存取權限歸類呢?這是因為物件導向程式設計允許後續定義的類別繼承 (inherit) 之前定義類別的特性,這樣的機制使 public 成員會被繼承,而 private 不能被繼承。還有另一個存取標籤 protected ,不過這不在我們目前的討論範圍。

我們舉一例如下


001 #include <iostream>
002
003 using namespace std;
004
005 // 宣告類別
006 class Demo {
007 // 宣告 public 成員
008 public:
009    int a;
010    int b;
011    int DoSomething();
012 };
013
014 // 實作 Demo 的 DoSomething() 成員函數
015 int Demo::DoSomething() {
016    return a + b;
017 }
018
019 // 程式執行的 main()
020 int main(void) {
021    // 宣告並建立 Demo 型態的物件 t
022    Demo t;
023    t.a = 11; // 直接設定成員變數值
024    t.b = 22;
025
026    cout << endl;
027    // 呼叫並印出 DoSomething() 的回傳值
028    cout << t.DoSomething() << endl;
029    cout << endl;
030
031    return 0;
032 }
033
034 /* 檔名: class_demo.cpp
035    作者: Kaiching Chang
036    時間: 2014-5 */

此例中的 Demo 類別宣告三個 public 成員, ab 為成員變數, DoSomething() 為成員函數,記得, class 大括弧的最後要加上分號


005 // 宣告類別
006 class Demo {
007    // 宣告 public 成員
008    public:
009       int a;
010       int b;
011       int DoSomething();
012 };

底下為實作 Demo 類別中的 DoSomething() 成員函數


014 // 實作 Demo 的 DoSomething() 成員函數
015 int Demo::DoSomething() {
016    return a + b;
017 }

DoSomething() 的工作很簡單,就是回傳兩個成員變數 ab 的相加值。這裡須注意定義成員函數時,必須在成員函數名稱前加上所屬類別名稱接兩個冒號


015 int Demo::DoSomething() {

這是標明 DoSomething() 是屬於 Demo 類別的,連續兩個冒號 :: 為作用域運算子 (scope operator) 。沒有這樣寫的話,編譯器 (compiler) 會把 DoSomething() 當成普通的函數處理。


也可以直接把成員函數的實作直接寫在宣告的地方,我們建議分開寫,因為小程式可能看起來沒差,大型程式在習慣上會把宣告放在標頭檔 (header file) 。

下面的 main() 直接用小數點運算子設定 ab ,然後印出 DoSomething() 的回傳值


019 // 程式執行的 main()
020 int main(void) {
021    // 宣告並建立 Demo 型態的物件 t
022    Demo t;
023    t.a = 11; // 直接設定成員變數值
024    t.b = 22;
025
026    cout << endl;
027    // 呼叫並印出 DoSomething() 的回傳值
028    cout << t.DoSomething() << endl;
029    cout << endl;
030
031    return 0;
032 }

編譯執行看看結果吧



這個例子我們只用到 public ,接下來我們要繼續介紹 private ,將資料有效的封裝 (encapsulation) 在物件裡。


中英文術語對照


類別 class
物件 object
關鍵字 keyword
宣告 declare
成員 member
資料 data
函數 function
建構函數 constructor
變數 variable
資料成員 data member
成員函數 member function
回傳值 return value
存取標籤 accsee label
繼承 inherit
作用域運算子 scope operator
標頭檔 header file
編譯器 compiler
封裝 encapsulation

重點整理


  1. 類別是物件的藍圖,每一個類別都可以定義資料成員及成員函數,宣告類別使用關鍵字 class ,每個成員都要用存取標籤分類,大括弧的最後要加上分號。
  2. 建構函數屬於特別的成員函數,用來建立該類別的物件。
  3. 成員函數的實作通常會放在類別宣告外,需要標上類別名稱與作用域運算子表示屬於哪個類別。
  4. 宣告建立類別的物件(變數)後,可用小數點運算子指派數值給 public 的成員變數,也可用小數點運算子呼叫成員函數。

問題與討論


  1. 為什麼類別要有專屬的變數及函數?想一想,這跟物件的意涵有什麼關聯?
  2. 成員函數跟一般的函數有什麼不同?資料成員跟一般的變數又有什麼不同?
  3. 除了建構函數、成員函數及資料成員之外,類別中還有其他種類的成員嗎?
  4. 為什麼要有建構函數?建構函數的用途是什麼?
  5. 為什麼成員函數的實作要放在類別宣告之外?

練習


  1. 寫一個程式 exercise1001.cpp ,裡頭設計一個類別 IntegerDemoIntegerDemo 有一個 int 的成員變數 value ,另有一個沒有回傳值的成員函數 add()add() 有一個 int 參數,呼叫 add() 時會把參數與 value 相加,結果儲存在 value ,執行部分先將 value 設定為 25 ,再呼叫 add()24 當參數。
  2. 承上題,另寫一個程式 exercise1002.cpp ,改成由使用者輸入兩個整數。
  3. 承上題,另寫一個程式 exercise1003.cpp ,加入成員函數 subtract()subtract() 沒有回傳值另外需要一個 int 參數,同樣呼叫 subtract() 是將 value 減去參數值,最後結果儲存在 value
  4. 承上題,另寫一個程式 exercise1004.cpp ,繼續擴充 IntegerDemo ,加入乘法的成員函數。
  5. 承上題,另寫一個程式 exercise1005.cpp ,繼續擴充 IntegerDemo ,加入除法的成員函數。
  6. 寫一個程式 exercise1006.cpp ,仿照 IntegerDemo ,將成員函數改成計算階層值,結果儲存在 value
  7. 寫一個程式 exercise1007.cpp ,仿照 IntegerDemo ,將成員函數改成計算費氏數列,結果儲存在 value

the end

沒有留言: