ヘッダファイルへのヘッダファイルのインクルード/インクルードを追加する癖があります。一方では、ヘッダーファイルに前方宣言を記述し、実際の#includeまたは#import行を実装ファイルに書き込みます。ヘッダファイルまたはインプリメンテーションファイルの#import
標準的な方法はありますか?どちらが良いの?
ヘッダファイルへのヘッダファイルのインクルード/インクルードを追加する癖があります。一方では、ヘッダーファイルに前方宣言を記述し、実際の#includeまたは#import行を実装ファイルに書き込みます。ヘッダファイルまたはインプリメンテーションファイルの#import
標準的な方法はありますか?どちらが良いの?
#include
X.hからのすべての場合、#include <X.h>
のクライアントには、Xで必要なものもありますが、Xのクライアントにはこれらすべてのヘッダーも含まれます。
X.hには、X.hの解析に必要なものだけを含める必要があります。並べ替えのインクルージョンがクライアントを壊さないようにするために、翻訳ユニットが他のヘッダーをインクルードすることは想定していないはずです。 X.cには、実装に必要な追加情報が含まれている必要があります。
これにより、再コンパイルの依存関係が最小限に抑えられます。実装にのみ変更を加えてヘッダーに影響を与え、クライアントの再コンパイルをトリガする必要はありません。あなたは単にX.c.から直接インクルードするべきです。
クラスの依存関係が浅い場合、ヘッダーの代わりに前方参照を含める必要があります。たとえば、次のように
A.h
#include "B.h"
class A {
B* pointer;
};
B.h
#include "A.h"
class B {
A* pointer;
};
コンパイル時に解除されます。
class A; class B { A* pointer; };
が各クラスとして動作しますA.h
class B;
class A {
B* pointer;
};
B.h
は、他のクラスが宣言に存在するかを知る必要があります。すべての実装ファイルにインクルードディレクティブが1つしかないように、ヘッダファイルにインポートを書きます。これには、モジュールのコードのユーザーからの依存関係を隠すという利点もあります。
しかし、同じ隠蔽には欠点があります。あなたのモジュールのユーザーは、ヘッダーに含まれるすべての種類の他のヘッダーをインポートしている可能性があります。そのような観点から、依存ファイルを手動で解決することを意味していても、実装ファイルに包含ディレクティブを含める方が、より軽いコードにつながります。
私は1つの答えはないと思います。私が与えた理由を考慮して、私は最初のアプローチを好む、私はそれがクリーンなコードにつながると思う(重くて、おそらく不必要なインポートを伴う)。
私は引用している(そしてその言葉が正確ではない)ことを覚えていませんが、私はいつも読むことを覚えています。 "人間は読むためにプログラムが書かれています。私のモジュールのユーザーがきれいに簡単にインポートでき、1つのディレクティブで使用できる限り、数キロバイトのコードが必要な場合は特に気にしません。
また、私は考慮しなかったことがない限り、それは味の問題だと思います。その場合、コメントは歓迎以上のものです!
乾杯。
申し訳ありませんが、あなたのロジックはうまくいきます。第1段落:「これは、モジュールのコードのユーザーからの依存関係を隠す利点もあります。/"彼がきれいにして、簡単にそれをインポートし、単一の指示でそれを使うことができる限り"。ヘッダーを解析するために必要なものを含める必要があります。実装にのみ必要な他のヘッダーは、クライアントが機能を使用するために含める必要はありません。 (どちらの方法でも、クライアントはオブジェクト/ライブラリに依然としてリンカの依存関係を追加する必要があります。) –
私の論理がどのように乱れているのか正直には分かりません。コンパイル行にファイルを追加するのと同じではなく、コード内に複数のモジュールを読み込むように強制するのではありません。私が見ているのは、あなたが非常に侮蔑的であるということです。それ以上コメントしないでください。私はこれに関する記事を見て、私の心を作ります。 – slezica
現実世界でこのような循環依存関係を持つのは良い設計/アーキテクチャですか? – Mugunth
いいえ、そうではありません。可能な限り避けるべきです。やむを得ない場合に、2つのモジュールが相互に組み込む必要がある場合、99%の場合、それらは意味的に1つの同じモジュールであるか、または両方に依存する組み合わされた基本モジュールのスーパーモジュールになります。 – slezica
AとBの前方宣言ヘッダーを提供することがより良い方法です。それぞれ、 "クラスA"と "クラスB"のみを含み、それぞれA.hとB.hの両方に含まれています。そうすることで、Aの前方宣言、宣言、実装は、Aから何かを構築するときに自然にクロスリファレンスされるので、クラスAからいくつかのテンプレートとtypedefを変更すると、BはコンパイラにAはです。 –