函數 (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
沒有留言:
張貼留言