web-dev-qa-db-ja.com

1つ以上のファイルでC ++クラスを定義する

C++クラスを作成するときのベストプラクティス>

  • クラス定義全体とメンバー関数をヘッダーファイルに配置する
  • クラス定義と関数宣言をヘッダーファイルに入れ、関数定義を別のソースファイルに入れます。
  • クラス定義全体を記述し、メンバー関数をソースファイルに宣言しますか?

私はあなたがこれらの3つの方法のいずれかでそれを行うことができることを理解していますが、私は優先/最速の方法があるかどうか疑問に思っています。どんな情報でもいいでしょう。

3
Mark Skelton

それはいつものように異なります。

通常、各クラスをヘッダー(.hまたは.hpp)およびソース(.cpp)ファイル。ここで、ソースファイルにできる限りすべてのものを入れます*。これにより、プログラムの構築がかなり高速化されます。大規模なプロジェクトでは、完全に再コンパイルしてリンクするのに15分から数時間かかることがあるため、これは実際の開発では非常に重要です。ソースファイルの内容を変更した場合、コンパイラはそのcppファイルをオブジェクトファイルに再コンパイルし、このオブジェクトファイルを含むプログラムをリンクするだけで済みます。ヘッダーファイルで何かを変更した場合、コンパイラーはそのヘッダーを含むすべてのcppファイルを再コンパイルし、これらのオブジェクトファイルのいずれかを含むすべてのプログラムをリンクする必要があります。

クラスが軽量で変更される可能性が非常に低い場合は、通常、すべてをヘッダーファイルに含めることをお勧めします。例としては、厳密に型指定されたIDとして機能し、コンストラクターと比較演算子のみを持つクラスがあります。ヘッダーファイルのみを使用すると、コードがよりシンプルで読みやすくなります。この特別なケースでは、クラスが変更されることはないため、コンパイル時間に悪影響を与えることはありません。

クラスがテンプレートの場合、通常はcppファイルに何も入れることはできません(テンプレートの特殊化を使用しない限り)が、多くの場合、inlineキーワードを使用してコンパイルできます。


*プロジェクトがヘッダーの依存関係とその結果のコンパイル時間の影響を強く受けている場合は、ソースファイルにさらに追加することができます。 pImpl Idiom

9
Peter

通常、クラス定義と関数宣言はヘッダーファイルに記述します。そして、ソース(* .cpp)ファイル内の関数定義。

クラス定義と関数宣言をヘッダーファイルに配置する理由は、ソフトウェアの他の部分がヘッダーをインクルードし、クラスとそのメソッドを使用できるようにするためです。
メソッド定義をcpp-sourceファイルに入れる理由wasメソッドは一度だけ定義する必要があるため。最新のコンパイラー(つまり、C++-14以降)は、同じメソッドを複数回定義できます(含まれているヘッダーファイルの場合のように、すべての定義が等しい場合)。ただし、ほとんどのC++プログラマーは、メソッド定義がcpp-filesにあり、メソッドをインライン化する必要がある場合にのみヘッダーファイルにあると想定しているため、cpp-filesにメソッドを配置することをお勧めします。

2

これはおそらく主観的ですが、興味深い質問です。 C++のクラスは、いくつかの異なる概念を表すために使用されます。

  1. インターフェース
  2. オブジェクト
  3. タイプ

インターフェイスにはvirtual void foo() = 0が含まれ、(うまくいけば)実装は含まれません。オブジェクトは、いくつかの状態をいくつかの関連するメソッドにバンドルします。 std::vector<int>。タイプは、コンパイルプロセスを制御するために使用されますが、これ以上の目的はありません-struct tag;またはstruct tag {}のように単純な場合もあります。

クラスとメソッドを分割する必要があるかどうかは、上記のカテゴリのどれを使用しているかに依存すると思います。インターフェイスは、ソースファイルにできるすべてのものを移動します。オブジェクトは、ヘッダーに記述された小さなインラインメソッドと、ソースにおそらく依存関係がある大きな関数が混在している可能性があります。純粋なタイプは、テンプレートと完全にヘッダーに含まれる傾向があります。

そうは言っても、「ベストプラクティス」のほとんどの形態は、重複の最小化と結合の最小化(間の妥協)に相当します。これらの目標をクラスに適用する場合は、結合を最小限に抑えるために他の場所からソースファイルに依存関係を引き込むメソッドを配置し、その他のメソッドをヘッダーに配置して、それほど多く入力する必要がないようにする必要があります。クラスを完全にソースファイルに書き込むことは、他のコンパイルユニットと共有する必要があるまではすばらしいですが、それまではそれで十分です。

これはテンプレートによって複雑になります。問題のクラスがテンプレート化されている場合、そのほとんどをヘッダーに書き込むか、単一のソースファイル内の既知のタイプのセットに対して明示的にインスタンス化するかを選択する必要があります。私はそれをベストプラクティスとして守ることはできませんでしたが、テンプレートクラスを完全にヘッダーファイルに記述し、型に依存しないコードをフリー関数に除外する傾向があります。

1