「ヘッダファイル」の版間の差分
C++で提案中のモジュールについての記載を追加 |
|||
7行目: | 7行目: | ||
== 背景 == |
== 背景 == |
||
最近の多くの[[プログラミング言語]]では、[[プログラム (コンピュータ)|プログラム]]は[[サブルーチン]]などの小さなコンポーネントに分割されており、各サブルーチンは複数の物理的に分割された[[ファイル (コンピュータ)|ファイル]]に配置され、個々にコンパイルされる。あるサブルーチンがそのファイル以外で定義された何かを使う場合、[[前方宣言]]や[[関数プロトタイプ]]といった概念を導入する必要が生じる。例えば、あるソースファイルに次のように関数が定義されるとする。 |
最近の多くの[[プログラミング言語]]では、[[プログラム (コンピュータ)|プログラム]]は[[サブルーチン]]などの小さなコンポーネントに分割されており、各サブルーチンは複数の物理的に分割された[[ファイル (コンピュータ)|ファイル]]に配置され、個々にコンパイルされる。あるサブルーチンがそのファイル以外で定義された何かを使う場合、[[前方宣言]]や[[関数プロトタイプ]]といった概念を導入する必要が生じる。例えば、あるソースファイルに次のように関数が定義されるとする。 |
||
< |
<syntaxhighlight lang="c"> |
||
int add(int a, int b) |
int add(int a, int b) |
||
{ |
{ |
||
return a + b; |
return a + b; |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
この関数を別のソースファイルで参照するには、[[関数プロトタイプ]]で宣言する必要がある。従って、次のようになる。 |
この関数を別のソースファイルで参照するには、[[関数プロトタイプ]]で宣言する必要がある。従って、次のようになる。 |
||
< |
<syntaxhighlight lang="c"> |
||
extern int add(int, int); |
extern int add(int, int); |
||
21行目: | 21行目: | ||
return add(x, add(x, x)); |
return add(x, add(x, x)); |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
しかし、この単純な手法ではプログラマが <code>add</code> という関数の宣言を二箇所で管理しなければならなくなる。すなわち、実装が書かれたファイルとそれを使っているファイルである。その関数の定義が変更された場合、プログラマはプログラムのあちこちにある関数プロトタイプも全て更新しなければならない。 |
しかし、この単純な手法ではプログラマが <code>add</code> という関数の宣言を二箇所で管理しなければならなくなる。すなわち、実装が書かれたファイルとそれを使っているファイルである。その関数の定義が変更された場合、プログラマはプログラムのあちこちにある関数プロトタイプも全て更新しなければならない。 |
||
27行目: | 27行目: | ||
ヘッダファイルはこの問題を解決するものである。モジュール化されたヘッダファイルでは、その[[モジュール]]が外部に公開する個々の関数、オブジェクト、データ型などの宣言をする。例えば、上記の例ではヘッダファイルには <code>add</code> の宣言が含まれるだろう。<code>add</code> を使っている各ソースファイルでは、そのヘッダファイルを <code>#include</code> ディレクティブを使って導入する。 |
ヘッダファイルはこの問題を解決するものである。モジュール化されたヘッダファイルでは、その[[モジュール]]が外部に公開する個々の関数、オブジェクト、データ型などの宣言をする。例えば、上記の例ではヘッダファイルには <code>add</code> の宣言が含まれるだろう。<code>add</code> を使っている各ソースファイルでは、そのヘッダファイルを <code>#include</code> ディレクティブを使って導入する。 |
||
< |
<syntaxhighlight lang="c"> |
||
#ifndef H_ADD |
#ifndef H_ADD |
||
#define H_ADD |
#define H_ADD |
||
34行目: | 34行目: | ||
#endif |
#endif |
||
</syntaxhighlight> |
|||
</source> |
|||
< |
<syntaxhighlight lang="c"> |
||
#include "add.h" |
#include "add.h" |
||
43行目: | 43行目: | ||
return add(x, add(x, x)); |
return add(x, add(x, x)); |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
これにより保守の負担が低減される。定義が変更された場合、ヘッダファイルにある宣言だけを更新すれば済む(変更内容によってはそれだけでは済まないこともある)。ヘッダファイルは、その中で宣言されたものの実体が定義されているソースファイルにもインクルードされることがある。これにより、コンパイラが定義と宣言が一貫しているかをチェックできる。 |
これにより保守の負担が低減される。定義が変更された場合、ヘッダファイルにある宣言だけを更新すれば済む(変更内容によってはそれだけでは済まないこともある)。ヘッダファイルは、その中で宣言されたものの実体が定義されているソースファイルにもインクルードされることがある。これにより、コンパイラが定義と宣言が一貫しているかをチェックできる。 |
||
< |
<syntaxhighlight lang="c"> |
||
#include "add.h" |
#include "add.h" |
||
54行目: | 54行目: | ||
return a + b; |
return a + b; |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
一般にヘッダファイルは[[インタフェース (情報技術)|インタフェース]]だけを提示するのに使われ、そこで宣言されたコンポーネントの使い方をある程度解説する文書を(コメントなどで)含んでいることが多い。上記の例では、サブルーチンの実装は別のソースファイルにあり、個別にコンパイルされる。C言語やC++における例外として[[インライン関数]]がある。多くの実装ではインライン関数の展開はコンパイル時にその定義がないとできない実装になっていることが多いためである。 |
一般にヘッダファイルは[[インタフェース (情報技術)|インタフェース]]だけを提示するのに使われ、そこで宣言されたコンポーネントの使い方をある程度解説する文書を(コメントなどで)含んでいることが多い。上記の例では、サブルーチンの実装は別のソースファイルにあり、個別にコンパイルされる。C言語やC++における例外として[[インライン関数]]がある。多くの実装ではインライン関数の展開はコンパイル時にその定義がないとできない実装になっていることが多いためである。 |
2020年7月5日 (日) 22:55時点における版
ヘッダファイル(英: Header file)は、特にC言語やC++でのプログラミングで使われるファイルであり、一般にソースコード形式をしていて、コンパイラが別のソースファイルの一部として自動的に展開して使用する。一般にヘッダファイルは、ソースファイルの先頭部分に書かれたディレクティブによってインクルード(その場に内容を展開)される。インクルードファイル(英: Include file)とも。
ヘッダファイルには、サブルーチンや変数やその他の識別子の前方宣言が含まれていることが多い。複数のソースファイルで宣言する必要のある識別子を1つのヘッダファイルに置き、必要に応じて個々のソースファイルがそのヘッダファイルをインクルードする。
C言語やC++では、標準ライブラリ関数はヘッダファイルで宣言されている。詳しくは、標準Cライブラリと標準C++ライブラリを参照されたい。
背景
最近の多くのプログラミング言語では、プログラムはサブルーチンなどの小さなコンポーネントに分割されており、各サブルーチンは複数の物理的に分割されたファイルに配置され、個々にコンパイルされる。あるサブルーチンがそのファイル以外で定義された何かを使う場合、前方宣言や関数プロトタイプといった概念を導入する必要が生じる。例えば、あるソースファイルに次のように関数が定義されるとする。
int add(int a, int b)
{
return a + b;
}
この関数を別のソースファイルで参照するには、関数プロトタイプで宣言する必要がある。従って、次のようになる。
extern int add(int, int);
int triple(int x)
{
return add(x, add(x, x));
}
しかし、この単純な手法ではプログラマが add
という関数の宣言を二箇所で管理しなければならなくなる。すなわち、実装が書かれたファイルとそれを使っているファイルである。その関数の定義が変更された場合、プログラマはプログラムのあちこちにある関数プロトタイプも全て更新しなければならない。
ヘッダファイルはこの問題を解決するものである。モジュール化されたヘッダファイルでは、そのモジュールが外部に公開する個々の関数、オブジェクト、データ型などの宣言をする。例えば、上記の例ではヘッダファイルには add
の宣言が含まれるだろう。add
を使っている各ソースファイルでは、そのヘッダファイルを #include
ディレクティブを使って導入する。
#ifndef H_ADD
#define H_ADD
extern int add(int, int);
#endif
#include "add.h"
int triple(int x)
{
return add(x, add(x, x));
}
これにより保守の負担が低減される。定義が変更された場合、ヘッダファイルにある宣言だけを更新すれば済む(変更内容によってはそれだけでは済まないこともある)。ヘッダファイルは、その中で宣言されたものの実体が定義されているソースファイルにもインクルードされることがある。これにより、コンパイラが定義と宣言が一貫しているかをチェックできる。
#include "add.h"
int add(int a, int b)
{
return a + b;
}
一般にヘッダファイルはインタフェースだけを提示するのに使われ、そこで宣言されたコンポーネントの使い方をある程度解説する文書を(コメントなどで)含んでいることが多い。上記の例では、サブルーチンの実装は別のソースファイルにあり、個別にコンパイルされる。C言語やC++における例外としてインライン関数がある。多くの実装ではインライン関数の展開はコンパイル時にその定義がないとできない実装になっていることが多いためである。
代替手法
ヘッダファイル以外にも、他のファイルで定義された識別子の宣言にアクセスする方法はある。ヘッダファイルの場合、実装しているファイルと宣言しているヘッダファイルの2ヶ所の更新を同期させる必要がある。
ヘッダーファイルという方法を用いないプログラミング言語もある。Javaなどの言語では、パッケージにより、コンパイラが把握できるようにしている。モジュールという名称で、同様の機能を有する言語もある。C++においても、モジュールの仕組みが提案されている[1]。
脚注
- ^ “A Module System for C++ (Revision 4)” (PDF) (英語). JTC1/SC22/WG21 - The C++ Standards Committee (2016年2月15日). 2016年6月5日閲覧。