はじめに
C++でプログラムが大きくなってくると、全てのコードを一つのmain.cpp
ファイルに記述するのは非効率で、管理も大変になります。オブジェクト指向プログラミングでは、クラスや関連する関数を、機能ごとにファイルに分割するのが一般的です。
このファイル分割の中心となるのが、「ヘッダーファイル (.h
or .hpp
)」と「ソースファイル (.cpp
)」です。
- ヘッダーファイル: 「こんな機能(関数やクラス)がありますよ」という宣言を記述する、いわば「目次」や「インターフェース」の役割を担います。
- ソースファイル: ヘッダーファイルで宣言された機能の、**具体的な処理内容(実装)**を記述します。
この記事では、簡単な関数を例に、C++のプログラムを複数のファイルに分割する基本的な方法と、そのメリットについて解説します。
ソースファイルを分割するサンプルコード
この例では、2つの数値を比較して大きい方を返す findGreater
という関数を、3つのファイルに分割して実装します。
1. ヘッダーファイル (math_utils.h
)
関数のプロトタイプ宣言(どのような引数を取り、どのような値を返すかという定義)を記述します。
// --- math_utils.h ---
// 2つの整数のうち、大きい方を返す関数のプロトタイプ宣言
int findGreater(int a, int b);
2. 関数のソースファイル (math_utils.cpp
)
ヘッダーファイルで宣言した関数の、実際の処理内容を記述します。
// --- math_utils.cpp ---
#include "math_utils.h" // 対応するヘッダーファイルをインクルード
// findGreater関数の実装(本体)
int findGreater(int a, int b) {
if (a > b) {
return a;
} else {
return b;
}
}
3. メインのソースファイル (main.cpp
)
作成した関数を利用する側のコードです。
// --- main.cpp ---
#include <iostream>
#include "math_utils.h" // 自作したヘッダーファイルをインクルード
using namespace std;
int main() {
int val1, val2, result;
cout << "1番目の整数を入力: ";
cin >> val1;
cout << "2番目の整数を入力: ";
cin >> val2;
// findGreater関数を呼び出す
result = findGreater(val1, val2);
cout << "大きい方の値は " << result << " です。" << endl;
return 0;
}
コードの解説とコンパイル
#include "math_utils.h"
#include
は、指定されたファイルの内容をその場に展開するプリプロセッサ命令です。
<iostream>
:<>
で囲むのは、C++が標準で用意している標準ライブラリのヘッダーファイルです。"math_utils.h"
:""
で囲むのは、自分で作成したローカルなヘッダーファイルです。
main.cpp
と math_utils.cpp
の両方で math_utils.h
をインクルードすることで、コンパイラは findGreater
関数の存在と使い方を認識し、ソースファイル同士を正しくリンクさせることができます。
ファイル分割のメリット
- コードの再利用性:
math_utils.h
とmath_utils.cpp
のセットは、他のプロジェクトでも再利用可能な「部品」となります。 - コンパイル時間の短縮: プログラムを修正した際に、変更があったソースファイルだけを再コンパイルすればよいため、大規模なプロジェクトではコンパイル時間が大幅に短縮されます。
- 可読性と保守性の向上: 機能ごとにファイルが分かれているため、どこに何が書かれているかが見通しやすくなります。
まとめ
今回は、C++プログラムをヘッダーファイルとソースファイルに分割する、基本的な方法を解説しました。
- ヘッダーファイル (
.h
): 関数の宣言(インターフェース)を置く。 - ソースファイル (
.cpp
): 関数の実装(処理内容)を置く。 - 利用する側は、ヘッダーファイルを
#include
する。
この「宣言と実装の分離」は、C++だけでなく、多くのコンパイラ型言語における基本であり、再利用可能でメンテナンスしやすいソフトウェアを構築するための第一歩です。