現在のコンパイラ技術やエコシステムの事情では好ましくないので C++ のプログラムの分割の仕組みは整理されなおしています。 C++20 (C++ の 2020 年の改定) ではモジュールという概念が導入され、インポート宣言で他のモジュールの機能を取り込むことができるようになりました。 まだ基本機能が入っただけで標準ライブラリがモジュールとして再構成されていないなど実際の活用には時期尚早ですが、より現代的な機能はすでに採用されています。
新しい機能は横に置いて、旧来のシステムの事情を説明します。
C++ の処理は各種の解釈を「フェイズ」と呼ばれる段階に分けて処理することになっており、 #include
はかなり序盤に処理されます。 この時点はプログラムの内容をほとんど解釈しておらず、ただ字句をそっくりそのまま埋め込むだけです。
#include
は内容を理解しないということを利用してヘッダ以外を別ファイルに分離するという使い方がされる場合もありました。 以下のような事例です。
1,2,3,4
int main(void) {
int a[]= {
#include "hoge.csv"
};
}
むしろプログラムの内容に繰り返しがあるときに #include
を利用する (複数回おなじファイルを #include
する) という活用法も考えられ、勝手にガードされると困ります。
また実際にそのような事例はあるので途中で仕様変更することも出来ませんでした。
こうなっている初期の事情というのは C++ の設計方針として
- C++ は言語である (開発ツールの詳細を規定したり口出しはしない。 (実際にはリンカで使える識別子が短すぎるのを改善させる活動はしたようです。))
- C++ は不格好でも今、この瞬間に使える言語でなければならない (ツール類が C++ のために出揃うのを待っていられない。 C++ は現実の道具なので使えない仕様を作っても仕方がない。 現実的な仕様を目指す)
というものがあって C の開発ツールをほとんどそっくりそのまま使えるようにしたからです。 #include
は C のルールの踏襲です。
C の仕様が ANSI の仕様として確立したのは 1989 年ですが、それ以前から使われていたのを取りまとめる形での仕様です。 実際には 1970 年代の事情が C には反映されています。 ハードウェアは貧弱で、ソフトウェア技術も未熟、どういう言語仕様が正解なのか全然わからない。 そのときにはそれが正解と思えたからそうしたという以上の詳細な事情はないんじゃないでしょうか。
ちなみに C++ の歴史は 1979 年に "C with Classes" と名付けられた言語から始まっており、 C の後継としてではなくほとんど平行して発展しています。 C++ は C と足並みをそろえるという選択をしたので駄目な部分もある程度は真似ています。