C++ 入門指南 V2.00 - 單元 12 - 建構函數




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



為什麼會需要多載函數呢?這是因為多載函數可以處理不同型態的參數,例如我們需要一個將數字相加的函數


    int a = add(12, 32);

兩個參數 1232 都是整數,運用之前 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 有兩個資料成員 ab ,因此我們打算設置三種參數版本,分別是沒有參數、一個參數及兩個參數


    Demo();
    Demo(int);
    Demo(int, int);

沒有參數的建構子直接呼叫修改函數將 ab 都設定為整數 1 ,一個參數的建構子將 ab 都設定為參數值,至於兩個參數的建構子, 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

重點整理


  1. 具有多個參數版本的函數被稱為多載函數,也就是允許函數有不同的參數列。
  2. C++ 是強型態的程式語言,運算式中若有兩種不同的資料型態,就需要先進行型態轉換。
  3. 編譯器會替基本內建型態進行自動型態轉換。
  4. 函數只能有一個回傳值,若只有回傳值型態不同,這並不構成另一個多載函數。
  5. 建構函數的主要目的是設定變數成員。

問題與討論


  1. 為什麼兩個函數只有回傳值型態的不同,並不構成多載函數?
  2. 為什麼編譯器要替基本內建型態進行自動型態轉換?
  3. 建構函數的用途為何?除了設定變數成員外,建構函數還有其他功能嗎?

練習


  1. 寫一個程式 exercise1201.cpp ,利用 exercise1101.cpp 設計的 IntegerDemo ,加入建構函數。
  2. 寫一個程式 exercise1202.cpp ,利用 exercise1102.cpp 計算階層值的類別,加入建構函數。
  3. 寫一個程式 exercise1203.cpp ,利用 exercise1103.cpp 計算費氏數列的類別,加入建構函數。

the end

沒有留言: