
函數 (function) 可以有多個參數 (parameter) 版本,建構函數 (constructor) 亦同,具有多個參數版本的函數被稱為多載函數 (overloaded function)

為什麼會需要多載函數呢?這是因為多載函數可以處理不同型態的參數,例如我們需要一個將數字相加的函數
| int a = add(12, 32); |
兩個參數 12 與 32 都是整數,運用之前 Demo::do_something() 的實作即可完成,那假如參數有一個不是整數呢?
| double b = add(2.53, 32); |
由於 C++ 是強型態 (strong typing) 的程式語言,浮點數的 double 與整數 int 是不同的資料型態 (data type) ,計算兩種資料型態前要先做型態轉換,不然就有可能會出現無法預期的結果
| double add(double p_a, int p_b) { | |
| double c = (double) p_b; | |
| return p_a + c; | |
| } |
雖然編譯器會自動替基本內建型態 (primitive built-in type) 進行型態轉換,有些地方並不會出錯,可是有些地方就會出錯,保險一點就是我們養成型態轉換的習慣,只要型態不同,就自己加進轉換的程式碼。
多載函數的版本是依參數列中參數的數量與型態,函數只能有一個回傳值,若只有回傳值型態不同,這並不構成另一個多載函數。
建構函數的主要目的是設定資料成員 (data member) ,由於 Demo 有兩個資料成員 a 與 b ,因此我們打算設置三種參數版本,分別是沒有參數、一個參數及兩個參數
| Demo(); | |
| Demo(int); | |
| Demo(int, int); |
沒有參數的建構子直接呼叫修改函數將 a 與 b 都設定為整數 1 ,一個參數的建構子將 a 與 b 都設定為參數值,至於兩個參數的建構子, a 設定為第一個參數, b 設定為第二個參數,實作如下
| // 沒有參數的建構函數 | |
| Demo::Demo() { | |
| set_a(1); | |
| set_b(1); | |
| } | |
| // 一個參數的建構函數 | |
| Demo::Demo(int n1) { | |
| set_a(n1); | |
| set_b(n1); | |
| } | |
| // 兩個參數的建構函數 | |
| Demo::Demo(int n1, int n2) { | |
| set_a(n1); | |
| set_a(n1); | |
| set_b(n2); | |
| } |
寫成完整範例如下
| 001 | #include <iostream> |
| 002 | |
| 003 | using namespace std; |
| 004 | |
| 005 | class Demo { |
| 006 | // 宣告 public 的成員 |
| 007 | public: |
| 008 | Demo(); |
| 009 | Demo(int n1); |
| 010 | Demo(int n1, int n2); |
| 011 | void set_a(int n); |
| 012 | void set_b(int n); |
| 013 | int get_a(); |
| 014 | int get_b(); |
| 015 | int do_something(); |
| 016 | |
| 017 | // 宣告 private 的成員 |
| 018 | private: |
| 019 | int a; |
| 020 | int b; |
| 021 | }; |
| 022 | |
| 023 | // 沒有參數的建構函數 |
| 024 | Demo::Demo() { |
| 025 | set_a(1); |
| 026 | set_b(1); |
| 027 | } |
| 028 | |
| 029 | // 一個參數的建構函數 |
| 030 | Demo::Demo(int n1) { |
| 031 | set_a(n1); |
| 032 | set_b(n1); |
| 033 | } |
| 034 | |
| 035 | // 兩個參數的建構函數 |
| 036 | Demo::Demo(int n1, int n2) { |
| 037 | set_a(n1); |
| 038 | set_b(n2); |
| 039 | } |
| 040 | |
| 041 | int Demo::do_something() { |
| 042 | // 改成呼叫 getter 成員函數 |
| 043 | return get_a() + get_b(); |
| 044 | } |
| 045 | |
| 046 | // setter 與 getter 成員函數 |
| 047 | void Demo::set_a(int n) { |
| 048 | a = n; |
| 049 | } |
| 050 | |
| 051 | void Demo::set_b(int n) { |
| 052 | b = n; |
| 053 | } |
| 054 | |
| 055 | int Demo::get_a() { |
| 056 | return a; |
| 057 | } |
| 058 | |
| 059 | int Demo::get_b() { |
| 060 | return b; |
| 061 | } |
| 062 | |
| 063 | int main(void) { |
| 064 | Demo t1; |
| 065 | Demo t2(11); |
| 066 | Demo t3(11, 22); |
| 067 | |
| 068 | cout << endl; |
| 069 | cout << t1.do_something() << endl; |
| 070 | cout << t2.do_something() << endl; |
| 071 | cout << t3.do_something() << endl; |
| 072 | cout << endl; |
| 073 | |
| 074 | return 0; |
| 075 | } |
| 076 | |
| 077 | /* 檔名: class_demo3.cpp |
| 078 | 作者: Kaiching Chang |
| 079 | 時間: 2014-5 */ |
利用建構函數建立物件 (object) ,宣告變數 (variable) 時加小括弧即可,需要留意沒有參數的建構子不需要加小括弧
| 064 | Demo t1; |
| 065 | Demo t2(11); |
| 066 | Demo t3(11, 22); |
編譯執行結果如下

我們連續介紹了物件導向程式設計中的封裝與建構函數,接下來還有個寫 C++ 程式基本並且重要的主題,也就是設計專屬的標頭檔,下面我們繼續討論囉!
中英文術語對照
| 函數 | function |
| 參數 | parameter |
| 建構函數 | constructor |
| 多載函數 | overloaded function |
| 強型態 | strong typing |
| 資料型態 | data type |
| 基本內建型態 | primitive built-in type |
| 資料成員 | data member |
| 物件 | object |
| 變數 | variable |
重點整理
- 具有多個參數版本的函數被稱為多載函數,也就是允許函數有不同的參數列。
- C++ 是強型態的程式語言,運算式中若有兩種不同的資料型態,就需要先進行型態轉換。
- 編譯器會替基本內建型態進行自動型態轉換。
- 函數只能有一個回傳值,若只有回傳值型態不同,這並不構成另一個多載函數。
- 建構函數的主要目的是設定變數成員。
問題與討論
- 為什麼兩個函數只有回傳值型態的不同,並不構成多載函數?
- 為什麼編譯器要替基本內建型態進行自動型態轉換?
- 建構函數的用途為何?除了設定變數成員外,建構函數還有其他功能嗎?
練習
- 寫一個程式 exercise1201.cpp ,利用 exercise1101.cpp 設計的 IntegerDemo ,加入建構函數。
- 寫一個程式 exercise1202.cpp ,利用 exercise1102.cpp 計算階層值的類別,加入建構函數。
- 寫一個程式 exercise1203.cpp ,利用 exercise1103.cpp 計算費氏數列的類別,加入建構函數。
the end
沒有留言:
張貼留言