C++ クラスを作成するときは、特定のケースのみをヘッダーに含めます。私は前方宣言を好み、それが C++ でのベスト プラクティスであると信じています。しかし、多くの場合、Qt クラスには標準の Qt クラスである非常に多くのフィールドが含まれているため、それらすべてを前方宣言で記述することはあまり良い考えではないように思えます。好ましい方法はありますか?Qt には膨大なドキュメントがあるので、私の質問に対する回答があると思いますが、読み始めたばかりです。
5 に答える
私のルールは、ヘッダーファイルに、問題のヘッダーファイルで使用される機能を定義するファイルのみを含めることです。
ヘッダーにあるクラスへのポインターと参照があるFoo
が、ヘッダーがそれらのオブジェクトの1つを突いたり、インスタンス化したりすることはないとします。この場合、クラスの定義は必要ありません。必要なのは前方宣言だけです。
一方、型のオブジェクトを突き刺した場合Foo
、または型のデータメンバーまたは変数がある場合は、前方宣言では不十分ですFoo
。ここで完全な定義が必要なので、#include
クラスを定義するヘッダーファイルに移りましょうFoo
。(または、インライン関数定義で使用する場合は、そのインライン化を再考して、実装を別のソースファイルに配置することをお勧めします。)
ヘッダー ファイルには、「できること」が書かれているだけです。cpp
ファイルには、「この方法で行うことができ、それが私たちの意図です」と書かれています。
これはJvO用です-あなたは言います
これは常にトレードオフです。前方宣言により、次のことが強制されます。a)他のヘッダーファイルで転送されたクラスへのポインターのみを使用する。b)クラスを使用するすべての.cc/.cppファイルにヘッダーファイルをインクルードします。
これらは有効です:
class Ditto;
Ditto letsHaveANewOne();
void useIt(Ditto X);
では、ポインタはどこにありますか?
前方宣言は、依存関係を持つ必要性を回避します。これは、コンパイラが面倒な作業の一部をリンカにオフロードできるため、優れています。また、そのヘッダーファイルがあり、クラス宣言のためにファイルを開いたり、解析したりする必要がある多くのコードを検討してください。長期的には時間を節約できます。
前方宣言は、c)コードが流動的な状態にあり、大量の再コンパイルを回避したい場合にのみIMOが役立ちます。d)クラス宣言は巨大です。
上記を参照してください-これはデカップリングとも呼ばれます。試してみてください-長期的には時間を節約できます。
この目的のために、Qt は単なる C++ ライブラリです。確かに前方宣言を書き続けることができます。クラスが肥大化している場合は、UI (プレゼンテーション) とデータ/ロジック コードが 1 つのクラスに混在していることを示している可能性があります。責任を明確に分離することで、いくつかの複雑なクラスをより多くの単純なクラスに置き換えることができる場合があります。
これは常にトレードオフです。forward 宣言により、次のことが強制
されます。a) 他のヘッダー ファイルでは、転送されたクラスへのポインターのみを使用します。
b) クラスを使用するすべての .cc/.cpp ファイルにヘッダー ファイルを含めます。
どちらも少し面倒な場合があります。具体的には、a) 転送された宣言されたクラスへの参照を使用または返すことができず、ポイント b) を入力するのが煩わしく、C++ ファイルに #include の長いリストが生成されます。
前方宣言は、 c) コードが不安定な状態にあり、大規模な再コンパイルを避けたい場合にのみ IMO に役立ちます。
d) クラス宣言が巨大です。
ポイント c) は Qt には適用されません (ライブラリを毎日更新しない場合)。d) は適用されますが、コンパイラがサポートしている場合は、プリコンパイル済みヘッダー ファイルを使用することで軽減できます。
Qt (少なくとも 4.7) には、QtContainerFwd のコンテナー (リスト、セット、マップなど) を除いて、前方宣言がバンドルされていません。前方宣言の同じリストを何度も入力していることに気付いた場合は、これらの宣言を使用して独自のヘッダー ファイルを作成することを検討してください。