C++ 入門指南 V2.00 - 單元 13 - 設計專屬的標頭檔




標頭檔 (header file) 的目的在於組織程式原始碼 (source code) 檔案,類別 (class) 、函數 (function) 、常數 (constant) 或特定識別名稱的宣告 (declaration) 都放進標頭檔中,實作則放進實作的程式碼檔案裡



C++ 程式檔案的副檔名為 .cpp ,標頭檔的副檔名則是 .h

為什麼要這麼區分呢?因為標頭檔代表的是程式與程式間的介面 (interface) ,通常已經開發完成的程式只需要看介面就能獲悉如何使用,不需要在乎實際實作的細節,畢竟知道怎麼用就夠了,好不好用則是另外一回事囉!


就另一方面來說,這樣也比較容易維護程式碼,因為使用開發好的程式用前置處理指令 #include 進來就行了。簡單說,就是把介面跟實作分開,介面無須在每一次測試後都連同修改,有需要修正的地方只需要修正實作的部份即可。


我們以目前的 Demo 類別當例子,介紹如何切割介面與實作。首先, Demo 類別的宣告放進 class_demo4.h


001 // Demo 類別的標頭檔
002 // 僅有 Demo 類別的宣告
003 class Demo {
004    // 宣告 public 的成員
005    public:
006       Demo();
007       Demo(int);
008       Demo(int, int);
009       void set_a(int);
010       void set_b(int);
011       int get_a();
012       int get_b();
013       int do_something();
014
015    // 宣告 private 的成員
016    private:
017       int a;
018       int b;
019 };
020
021 /* 檔名: class_demo4.h
022    作者: Kaiching Chang
023    時間: 2014-5 */

實作放到相同檔名的 class_demo4.cpp


001 // 須引進標頭檔
002 #include "class_demo4.h"
003
004 // 沒有參數的建構函數
005 Demo::Demo() {
006    set_a(1);
007    set_b(1);
008 }
009
010 // 一個參數的建構函數
011 Demo::Demo(int n1) {
012    set_a(n1);
013    set_b(n1);
014 }
015
016 // 兩個參數的建構函數
017 Demo::Demo(int n1, int n2) {
018    set_a(n1);
019    set_b(n2);
020 }
021
022 int Demo::do_something() {
023    // 改成呼叫 getter 成員函數
024    return get_a() + get_b();
025 }
026
027 // setter 與 getter 成員函數
028 void Demo::set_a(int n) {
029    a = n;
030 }
031
032 void Demo::set_b(int n) {
033    b = n;
034 }
035
036 int Demo::get_a() {
037    return a;
038 }
039
040 int Demo::get_b() {
041    return b;
042 }
043
044 /* 檔名: class_demo4.cpp
045    作者: Kaiching Chang
046    時間: 2014-5 */

注意這裡用雙引號引入 class_demo4.h ,角括弧用在標準程式庫 (standard library) ,至於自己設計的標頭檔則是用雙引號


001 // 須引進標頭檔
002 #include "class_demo4.h"

class_demo4.cpp 中並沒有 main() ,因此我們需要另外設計一個包含 main().cpp 檔案


001 #include <iostream>
002
003 // 須引進標頭檔
004 #include "class_demo4.h"
005
006 using namespace std;
007
008 int main(void) {
009    Demo t1;
010    Demo t2(11);
011    Demo t3(11, 22);
012
013    cout << endl;
014    cout << t1.do_something() << endl;
015    cout << t2.do_something() << endl;
016    cout << t3.do_something() << endl;
017    cout << endl;
018
019    return 0;
020 }
021
022 /* 檔名: class_demo5.cpp
023    作者: Kaiching Chang
024    時間: 2014-5 */

classdemo5.cpp 同樣需要引入 classdemo4.h ,不然編譯器 (compiler) 會不認識 Demo 的名稱唷!


編譯時要把 classdemo4.cppclassdemo5.cpp 放在一起編譯,編譯執行結果如下



C++ 的程式基本認識大抵介紹到這裡,接下來,我們要發展一個編密碼的 Encrypt 類別,藉以介紹更多利用 C++ 開發軟體的概念。


中英文術語對照


標頭檔 header file
原始碼 source code
類別 class
函數 function
常數 constant
宣告 declaration
介面 interface
標準程式庫 standard library
編譯器 compiler

重點整理


  1. 標頭檔用來宣告類別、函數、常數或其他識別名稱。
  2. C++ 程式檔案的副檔名為 .cpp ,標頭檔的副檔名則是 .h
  3. 若定義類別的程式中沒有 main() ,就需要另一個有 main().cpp 程式來執行測試。

問題與討論


  1. 為什麼要額外定義標頭檔?標頭檔的用途為何?
  2. 程式中的介面跟實作有什麼不同?為什麼要把介面跟實作分開?
  3. 引進標準程式庫和自行定義的標頭檔,兩者的方式有差異嗎?

練習


  1. 寫一個程式 exercise1301.cpp 與 exercise1301.h ,利用 exercise1201.cpp 設計的 IntegerDemo ,將介面與實作分開。
  2. 寫一個程式 exercise1302.cpp 與 exercise1302.h ,利用 exercise1202.cpp 計算階層值的類別,將介面與實作分開。
  3. 寫一個程式 exercise1303.cpp 與 exercise1303.h ,利用 exercise1203.cpp 計算費氏數列的類別,將介面與實作分開。

the end

沒有留言: