カプセル化のクラスソースはヘッダだけというのは?

解決


7038  2003-02-13 15:11:44  No: 51037  IP: [192.*.*.*]

はじめまして。

突然ですが、気が狂っているわけではありません。
C++でソースを全てヘッダに記述するというのはどう思いますか?


C#なんかでは、ヘッダが存在しなくなりいきなりクラスを宣言してソースを
記述しますよね。

ソースを解析する際、インライン関数とクラス関数で2つのファイルを
またがって見るというのは非常に面倒であり、また完璧なクラスであれば
必要ありませんが、変更が加えられる場合ヘッダとソース2つを変更するのは
無駄だと感じます。

カプセル化されるクラスだけを、ヘッダ内に全て書き込むというのは
やはり不味いのでしょうか…

編集 削除
YuO  2003-02-13 16:07:39  No: 51038  IP: [192.*.*.*]

・コンパイルに時間がかかる
毎回全ての関数を構文解析・意味解析することになるためです。
class A;
としておけば済むはずだった物が,
class A { /* ... */ };
などと書けば,当然それだけ時間がかかります。

・動作を変更しただけで関係するファイルすべての再コンパイルが必要になる
次のような依存関係の時に,a.cppだけコンパイルすれば良かった物が,
a.cppの内容をa.hに入れてしまうとb.cppとc.cppまでコンパイルする必要が出てきます。
a.cpp: a.h
b.cpp: a.h
c.cpp: a.h

・内部結合を持つ関数だけなので,非常に無駄が多くなる
ヘッダに書く以上,定義は内部結合を持つ識別子のみとなります。
すると,全ての関数は内部結合を持つことになり,クラスを利用する全ての翻訳単位に同じ関数が含まれることになります。
もちろん,VC++のリンカのように一つに纏めることもできるでしょうが,
そのようなリンカだけではないですし。

・実装の詳細までクラス定義に入り込むと非常に読みにくい
JavaやC#でのクラス定義の一番の問題がこれだと思います。
ひとつのファイルに実装を全て書くとなると,クラスの定義自体が非常に長くなってしまいます。
C++の場合は,複数のファイルにメンバ関数の定義を分散させることで,
読みやすくなりますし,依存関係を減らすことが出来ます。

編集 削除
7038  2003-02-14 09:10:06  No: 51039  IP: [192.*.*.*]

YuOさん。
ご返答ありがとうございます。


>・コンパイルに時間がかかる
確かにそれはあります。


>・内部結合を持つ関数だけなので,非常に無駄が多くなる
無知ですみません。
VC++だけしか考えてませんでした。


>・実装の詳細までクラス定義に入り込むと非常に読みにくい
これは本当に読みにくくなるでしょうか。

確かに、クラス定義が長くなるのは少し問題がありますが
かといってファイルが増えるの方の分散が、良いとも思えません。

解析したいメンバ関数が他のファイルにあれば、当然ファイルを
いくつも調べなければならないと思いますし、ファイル数が増える
方にも問題があると思います。

あまりにも長くなるようであれば、クラスを派生させた方が分かりやすく
なると思いますし、派生は機能の拡張だけではなく、分離、分散の為にも
あると思います。

ただ、分離、分散させたクラスを多重継承により結合させるというやり方を
取らなければ良いですし、分かりやすくなると思うのですが、どうでしょう。

編集 削除
SSA  2003-02-14 09:42:39  No: 51040  IP: [192.*.*.*]

>>・実装の詳細までクラス定義に入り込むと非常に読みにくい
>これは本当に読みにくくなるでしょうか。

詳細な実装を知らなければ、使えないようなクラスの設計は間違っていると思います。

多人数で(大規模な)開発を行う場合、人の担当しているモジュールの実装まで確認して
いる暇などないし、実際不可能です。つまり、開発者の間で、関数等のインタフェース
さえ決めてしまえば、あとは担当者が中をどう実装しようが(どう実装を変更しようが)
関知しないし、依存もしない、というのがカプセル化ということだと思いますが。

そのために、基本的にはヘッダファイルには宣言(インタフェース)のみを書き、実装は
cppファイルに分離し、クラスの利用者はヘッダファイルさえ読めばよいようにすると。
まあ、実際はそこまで理想的ではないわけだけど^^;

編集 削除
SSA  2003-02-14 13:49:33  No: 51041  IP: [192.*.*.*]

>関知しないし、依存もしない、というのがカプセル化ということだと思いますが。

口がすべりました。
上記の話は別にカプセル化の話ではないですね。C言語でも同じことだし。

で、先程の私の発言は、最初の書き込みの
>必要ありませんが、変更が加えられる場合ヘッダとソース2つを変更するのは
>無駄だと感じます。

ここの部分への突っ込みであるべきでした。
ヘッダに変更が入るというのは、原則的にはインタフェースが変わるということだから
そうそう頻繁に起こってはならないことです。それが頻繁に起こるのは、設計が甘かった
ということですから。

とは言え、変更があった際に複数ファイルの整合性を保たないといけない、という
のは
保守性が悪いと言えるのかもしれませんし、実際、統合環境のような便利でない環境で
ソースを読んでいる時に、あちこちのファイルをたらい回しされると腹が立ってきますけどね^^

あと、YuOさんのコンパイル時間の話にも繋がりますが、大規模な開発の場合、フルビルド
するのに30分以上とか平気でかかったりします。cppの変更なら、そのファイルだけコンパイル
し直してリンクすれば済むので、すぐ終わりますが、ヘッダファイルに変更が入ると依存
関係にある全てのソースをコンパイルし直す必要が出てきて、鬱になります…

編集 削除
7038  2003-02-17 11:02:41  No: 51042  IP: [192.*.*.*]

>保守性が悪いと言えるのかもしれませんし、実際、統合環境のような便利でない環境で
>ソースを読んでいる時に、あちこちのファイルをたらい回しされると腹が立ってきますけどね^^

やはりそうですよね。(笑


>あと、YuOさんのコンパイル時間の話にも繋がりますが、大規模な開発の場合、フルビルド
>するのに30分以上とか平気でかかったりします。cppの変更なら、そのファイルだけコンパイル
>し直してリンクすれば済むので、すぐ終わりますが、ヘッダファイルに変更が入ると依存
>関係にある全てのソースをコンパイルし直す必要が出てきて、鬱になります…


そこまで大規模な開発を行ったことが無いので分かりませんでしたが、
確かにそうなるとかなりの時間の無駄になりますね。

結果、ヘッダだけというのは良く無いということが分かりました。

ありがとうございます。

編集 削除