Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

ヘッダファイルはどこへ向かっているのか

ヘッダファイルがどのように使われるかはわかりました。では「何故」ヘッダファイルが必要なのかという事を検討しましょう。

まず、このような小細工が必要な言語は、現代プログラミング言語ではC++しか無いという事を強調しておきます。これはくるしまぎれのアイデアなのです。Javaにはありません。C#にもありません。何故か? 「ヘッダをインクルードする」という作業はC言語時代の名残りであって、もはや必要の無い事だからです。

何故必要ないのか?

 そもそも、何故C++ではヘッダファイル(.h)と実装ファイル(.cpp)が分離されているのでしょうか? 入門書の中には「実装を隠蔽してインターフェイスを公開する為」とか書いているかもしれません。これは「嘘」です。少なくとも、後付けの理屈であることは間違いありません。

 何故、嘘なのか? 簡単な話です。隠蔽が目的なのであれば、privateメンバ(=公開されてはならないメンバ)がインターフェイスに含まれてはならない筈です。これについての合理的な説明はありません。C++では実装の完全な隠蔽は不可能なのです。

 これについては、「インターフェイスクラスを用意すればいい」「pimpleイディオムを利用すればいい」という反論もあると思います。ですが、どちらも言語仕様の不備をテクニックで補っているにすぎません。また、根本的な問題を解決していません。

 では、実装の隠蔽を目的としていないなら、何故ファイルが分かれているのでしょうか? Effective C ++から引用します。

 ……と思ったらEffective C ++には該当するコラムがありませんでした。メイヤー先生ごめんなさい(爆)。みはえるの予測でしゃべらせていただきますとですね(突然卑屈に)、分割コンパイルを実現する為なのですよ。C++言語が発表された当時、山のようなソースファイルをいっぺんにコンパイルする為にはマシンスペックが足りませんでした。

 そこで、ソースファイルを個別にコンパイルし、後でつなげるというアイデアが採用されました(ホントか?)。これを実現する為には、インクルードするファイルは最小限である事が望ましい。よって、ヘッダファイルにはオブジェクトファイルを生成するのに最低限必要な情報、つまりクラス宣言だけを記述するようになっているのです。

 おわかりでしょうか。つまり、少なくともC++におけるヘッダファイルという考え方は、低速、小容量、小メモリ環境において、現実的なコンパイル速度を叩く為に必要だった物であり、現在は無用の長物なのです。てゆーかいちいち.hと.cpp切り替えるのめんどくさいんだよまぢでっ!

他の言語ではどうか(C#を例にして)

 C#ではそもそもヘッダファイルという概念がありません(C++でのクラスがすべてインラインで記述されていると考えて下さい。こっちの方がずっと自然です)。当然インクルード文もありません。プロジェクトに含まれるソースファイルは一度すべて一本のファイルに連結され、その後プリプロセス処理が走ります。わかりやすい。

 ではインターフェイスの公開はどうするのか? 実装レベルではinterfaceというそのものずばりがあります。また、ドキュメントレベルではアセンブリというインターフェイス公開メカニズムがあります。これはソースコードを超えた概念です((もしかするとインターフェイスの公開と実装の隠蔽というのは、ソースコードに限定した言語仕様では実現出来ないのかもしれません))。Javaにもきっと似たような物があるでしょう*1

*1:Java以降のもっと新しい言語ではよりうまいアイデアが用いられているのかもしれませんが無勉強にて存じません

現実的にはどうか

 Visual C++では"#pragma once"というプリプロセッサ命令をヘッダファイルに入れる事によって、インクルードガードを実現します。これは素晴らしいギミックです。欲を言えば、「ヘッダファイルはすべて#pragma onge扱いにする」というオプションを用意して欲しいです。更に言えば(もうおわかりかもしれませんが)、C++の仕様で宣言の2重読み込みは無視するようにして欲しいのです。

ソースコード互換性なんてクソクラエだ

 ……などと言ったらCPPコミュニティに袋叩きにあいそうなので絶対に言いません(爆)。しかしですな、現実的に実現出来ない物を#ifdef分岐で個別対応してまで「どのプラットフォームでもコンパイル可能」と言うのはどうかと思うのですよ。

 それよりは、それぞれのプラットフォーム毎にソースを用意し、差分を管理するメカを別途用意した方が良いと思います(その差分管理が大変なんだけどな……)。Lokiの最近のバージョンはそういう形になってますね。あれが良い方法かといわれるとやっぱり「?」なのですが……。