C++ 入門指南

單元 13 - 設計專屬的標頭檔

本書已有新版,請參考 C++ 入門指南 4.01 - 單元 13 - 設計專屬的標頭檔

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

program.cpp → program.h

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

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

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

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

// Demo 類別的標頭檔,僅有 Demo 類別的宣告
class Demo {
// 宣告 public 的成員
public:
    Demo();
    Demo(int);
    Demo(int, int);
    void set_a(int);
    void set_b(int);
    int get_a();
    int get_b();
    int do_something();
    
// 宣告 private 的成員
private:
    int a;
    int b;
};

/* 《程式語言教學誌》的範例程式
   http://kaiching.org/
   檔名:class_demo4.h
   功能:示範定義標頭檔
   作者:張凱慶 */

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

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

// 沒有參數的建構函數
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::do_something() {
    // 改成呼叫 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;
}

/* 《程式語言教學誌》的範例程式
   http://kaiching.org/
   檔名:class_demo4.cpp
   功能:示範定義實作檔
   作者:張凱慶 */

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

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

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

#include <iostream>

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

using namespace std;

int main(void) {
    Demo t1;
    Demo t2(12);
    Demo t3(13, 24);
    
    cout << endl;
    cout << t1.do_something() << endl;
    cout << t2.do_something() << endl;
    cout << t3.do_something() << endl;
    cout << endl;
    
    return 0;
}

/* 《程式語言教學誌》的範例程式
   http://kaiching.org/
   檔名:class_demo5.cpp
   功能:示範定義實作檔
   作者:張凱慶 */

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

編譯時要把 classdemo4.cppclassdemo5.cpp 放在一起編譯,這裡切換到 TERMINAL 頁籤,改成直接下編譯指令編譯,編譯執行結果如下

-classdemo4-

由於 Visual Studio Code 的 Code Runner 預設只編譯執行一個程式檔案,這裡需要把兩個程式檔案放在一起編譯,切換到 TERMINAL 比較方便,之後也需要利用 TERMINAL 編譯執行。

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.cppexercise1301.h ,利用 exercise1201.cpp 設計的 IntegerDemo ,將介面與實作分開。
2. 寫一個程式 exercise1302.cppexercise1302.h ,利用 exercise1202.cpp 計算階層值的類別,將介面與實作分開。
3. 寫一個程式 exercise1303.cppexercise1303.h ,利用 exercise1203.cpp 計算費氏數列的類別,將介面與實作分開。

上一頁 單元 12 - 建構函數
回 C++ 入門指南首頁
下一頁 單元 14 - Encrypt 類別
回 C++ 教材
回程式語言教材首頁