物件導向程式設計 (object-oriented programming) 有三大基本特性,分別是封裝 (encapsulation) 、繼承 (inheritance) 及多型 (polymorphism)
繼承的目的是讓類別 (class) 具有像是親屬的垂直關係(父母子女),子類別 (subclass) 可以擁有父類別 (superclass) 的成員 (member) ,而多型像是親屬的平行關係(兄弟姊妹),多個子類別繼承自單一父類別之時,這些子類別就可以用父類別代替,父類別如同家族裡的「姓」,子類別則是「名」。
繼承的英文原文 inherit ,中文意思泛指從什麼得到什麼,生物學上的遺傳也是用這個詞。
至於封裝的意思就是把資料 (data) 封在類別中,這還牽涉到程式設計中另一個重要的概念 資訊隱藏 (information hiding) ,主要就是不讓外界隨意存取類別的資料,也就是說,只讓類別的資料成員 (data member) 給同個類別的成員函數 (member function) 存取。
這就要用到 private 存取標籤 (access label) 了,就是把成員變數放在 private 之後,而其他可供外界存取的成員函數放在 public 之後
class Demo {
// 宣告 public 的成員
public:
void set_a(int n);
void set_b(int n);
int get_a();
int get_b();
int DoSomething();
// 宣告 private 的成員
private:
int a;
int b;
};
這裡 a 與 b 已經改放到 private 之後,也由於 a 與 b 都是 private 的,因此另外宣告 public 的 set_a() 與 set_b() 設定 a 與 b 之值, get_a() 與 get_b() 取得 a 與 b 之值。
存取標籤後面要接一個冒號,之後的成員依縮排方式加入。
set_a() 與 set_b() 為修改函數 (mutator) ,就是俗稱的 setter ,至於 get_a() 與 get_b() 為存取函數 (accessor) ,也就是是俗稱的 getter 。
因此 set_a() 、 set_b() 、 get_a() 、 get_b() 的實作很簡單,如下
// setter 與 getter 成員函數
void Demo::set_a(int n) {
a = n;
}
void Demo::set_b(int n) {
b = n;
}
int Demo::get_a() {
return a;
}
int Demo::get_b() {
return b;
}
我們寫成一個完整範例,如下
#include <iostream>
using namespace std;
class Demo {
// 宣告 public 的成員
public:
void set_a(int n);
void set_b(int n);
int get_a();
int get_b();
int DoSomething();
// 宣告 private 的成員
private:
int a;
int b;
};
int Demo::DoSomething() {
// 改成呼叫 getter 成員函數
return get_a() + get_b();
}
// setter 與 getter 成員函數
void Demo::set_a(int n) {
a = n;
}
void Demo::set_b(int n) {
b = n;
}
int Demo::get_a() {
return a;
}
int Demo::get_b() {
return b;
}
int main(void) {
Demo t;
// 由呼叫 setter 設定成員變數
t.set_a(12);
t.set_b(23);
cout << endl << t.DoSomething() << endl << endl;
return 0;
}
/* 《程式語言教學誌》的範例程式
http://kaiching.org/
檔名:class_demo2.cpp
功能:示範定義類別
作者:張凱慶 */
編譯執行結果如下
但是這樣設定成員變數還得額外呼叫 set_a() 與 set_b() ,有點麻煩,我們希望宣告 (declare) 時就能夠直接設定,其實這用建構函數 (constructor) 就可以囉!
相關教學影片
- 類別 ⇨ YouTube 頁面連結
- 封裝 ⇨ YouTube 頁面連結
- static 、 const 與 mutable 成員 ⇨ YouTube 頁面連結
- 繼承 ⇨ YouTube 頁面連結
- 多型 ⇨ YouTube 頁面連結
- 標頭檔與標準程式庫 ⇨ YouTube 頁面連結
中英文術語對照 | |
---|---|
物件導向程式設計 | object-oriented programming |
封裝 | encapsulation |
繼承 | inheritance |
多型 | polymorphism |
類別 | class |
子類別 | subclass |
父類別 | superclass |
成員 | member |
資料 | data |
資訊隱藏 | information hiding |
資料成員 | data member |
成員函數 | member function |
存取標籤 | access label |
修改函數 | mutator |
存取函數 | accessor |
宣告 | declare |
建構函數 | constructor |
重點整理 |
---|
1. 物件導向程式設計有封裝、繼承及多型等三大基本特性。 |
2. 繼承像是親屬的重直關係(父母子女),多型則像是親屬的平行關係(兄弟姊妹)。 |
3. 封裝連帶的觀念就是資訊隱藏,類別的成員變數只能在類別中處理,因此要把資料成員宣告在 private 存取標籤下。 |
4. 外界要存取 private 的資料成員要透過 public 的存取函數與修改函數。 |
問題與討論 |
---|
1. 物件導向程式設計有哪三大基本特性? |
2. 什麼是封裝?為什麼要做封裝? |
3. 什麼是繼承?繼承機制有什麼優點? |
4. 什麼是多型?可以用什麼方式比擬嗎? |
5. 什麼是存取函數與修改函數?為什麼要有存取函數與修改函數? |
練習 |
---|
1. 寫一個程式 exercise1101.cpp ,利用 exercise1005.cpp 設計的 IntegerDemo ,替 value 加入存取函數與修改函數。 |
2. 寫一個程式 exercise1102.cpp ,利用 exercise1006.cpp 計算階層值的類別,替 value 加入存取函數與修改函數。 |
3. 寫一個程式 exercise1103.cpp ,利用 exercise1007.cpp 計算費氏數列的類別,替 value 加入存取函數與修改函數。 |