![](../../img/compile.jpg)
C++ 入門指南 4.01
單元 12 - 建構函數
![-unit12-](../../img/cpp_guide4/cpp_map_05.png)
函數 (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) 進行型態轉換,有些地方並不會出錯,可是有些地方就會出錯,保險一點就是我們養成型態轉換的習慣,只要型態不同,就自己加進轉換的程式碼。
多載函數的版本是依參數列中參數的數量與型態,函數只能有一個回傳值 (return value) ,若只有回傳值型態 (return 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); }
寫成完整範例如下
#include <iostream> using namespace std; class Demo { // 宣告 public 的成員 public: Demo(); Demo(int n1); Demo(int n1, int n2); void set_a(int n); void set_b(int n); int get_a(); int get_b(); int DoSomething(); // 宣告 private 的成員 private: int a; int 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_b(n2); } 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 t1; Demo t2(11); Demo t3(11, 22); cout << endl; cout << t1.DoSomething() << endl; cout << t2.DoSomething() << endl; cout << t3.DoSomething() << endl; cout << endl; return 0; } /* 《程式語言教學誌》的範例程式 http://kaiching.org/ 檔名:class_demo3.cxx 功能:示範定義類別 作者:張凱慶 */
利用建構函數建立物件 (object) ,宣告變數 (variable) 時加小括弧即可,需要留意沒有參數的建構函數不需要加小括弧
Demo t1; Demo t2(11); Demo t3(11, 22);
編譯執行結果如下
![-classdemo3-](../../img/cpp_guide4/class_demo3.png)
我們連續介紹了物件導向程式設計 (object-oriented programming) 中的封裝 (encapsulation) 與建構函數,接下來還有個寫 C++ 程式基本並且重要的主題,也就是設計專屬的標頭檔 (header file) ,下面我們繼續討論囉!
中英文術語對照 | |
---|---|
建構函數 | constructor |
資料成員 | data member |
資料型態 | data type |
封裝 | encapsulation |
函數 | function |
標頭檔 | header file |
物件 | object |
物件導向程式設計 | object-oriented programming |
多載函數 | overloaded function |
參數 | parameter |
基本內建型態 | primitive built-in type |
回傳值型態 | return type |
回傳值 | return value |
強型態 | strong typing |
變數 | variable |
重點整理 |
---|
1. 具有多個參數版本的函數被稱為多載函數,也就是允許函數有不同的參數列。 |
2. C++ 是強型態的程式語言,運算式中若有兩種不同的資料型態,就需要先進行型態轉換。 |
3. 編譯器會替基本內建型態進行自動型態轉換。 |
4. 函數只能有一個回傳值,若只有回傳值型態不同,這並不構成另一個多載函數。 |
5. 建構函數的主要目的是設定變數成員。 |
問題與討論 |
---|
1. 為什麼兩個函數只有回傳值型態的不同,並不構成多載函數? |
2. 為什麼編譯器要替基本內建型態進行自動型態轉換? |
3. 建構函數的用途為何?除了設定變數成員外,建構函數還有其他功能嗎? |
練習 |
---|
1. 寫一個程式 exercise1201.cxx ,利用 exercise1102.cxx 設計的 IntegerDemo ,加入兩個建構函數,第一個建構函數沒有參數,將 value 預設為 0 ,第二個建構函數利用參數設定 value ,然後把 set_value(int) 移到 private 標籤之下。 參考程式碼 |
2. 寫一個程式 exercise1202.cxx ,利用 exercise1103.cxx 計算階層值的類別,將 Compute() 的內容移到 set_value(int) 之內,然後利用建構函數呼叫 set_value(int) ,注意建構函數需要一個參數,然後把 set_value(int) 移到 private 標籤之下。 參考程式碼 |
3. 寫一個程式 exercise1203.cxx ,利用 exercise1104.cxx 計算費氏數列的類別,將 Compute() 的內容移到 set_value(int) 之內,然後利用建構函數呼叫 set_value(int) ,注意建構函數需要一個參數,然後把 set_value(int) 移到 private 標籤之下。 參考程式碼 |
4. 寫一個程式 exercise1204.cxx ,利用 exercise1105.cxx 的 Point 類別,加入建構函數呼叫修改函數設定 x 、 y 成員變數,增加 get_point() 回傳座標的字串形式,然後印出兩點座標及距離。 參考程式碼 |
5. 寫一個程式 exercise1205.cxx ,利用 exercise1106.cxx 的 Guess 類別,然後利用建構函數呼叫 set_a(string) ,注意建構函數需要一個參數,然後把 set_a(string) 移到 private 標籤之下。 參考程式碼 |
6. 寫一個程式 exercise1206.cxx ,利用 exercise1107.cxx 的 Member 類別,加入建構函數呼叫 set_id(int) 及 set_name(string) ,並把這兩個成員函數移到 private 標籤之下。 參考程式碼 |
7. 寫一個程式 exercise1207.cxx ,利用 exercise1108.cxx 的 Text 類別,然後利用建構函數呼叫 set_c(string) ,注意建構函數需要一個參數,然後把 set_c(string) 移到 private 標籤之下。 參考程式碼 |
8. 寫一個程式 exercise1208.cxx ,利用 exercise1109.cxx 的 Ball 類別,注意除了 Point 用上面 exercise1204.cxx 加入建構函數外, Ball 也加入建構函數,相關修改函數都移到 private 標籤之下。 參考程式碼 |
9. 寫一個程式 exercise1209.cxx ,利用 exercise1110.cxx 的 Scene 類別,加入建構函數呼叫修改函數設定 id 、 text 成員變數,然後利用建構函數呼叫 set_id(int) 與 set_text(string) ,注意建構函數需要兩個參數,然後把兩個修改函數移到 private 標籤之下。 參考程式碼 |
10. 寫一個程式 exercise1210.cxx ,利用 exercise1111.cxx 的 Ball 類別,注意除了 Guess 或 Ball 用上面練習加入建構函數外, Game 也加入建構函數,相關修改函數都移到 private 標籤之下。 參考程式碼 |
相關教學影片
- 類別 ⇨ YouTube 頁面連結
- 封裝 ⇨ YouTube 頁面連結
![](../../img/pydoing.gif)