web-dev-qa-db-ja.com

ヘッダーファイルに何があってはいけませんか?

ヘッダーファイルに絶対に含めるべきではないものは何ですか?

たとえば、多くの定数を持つドキュメント化された業界標準形式で作業している場合、それらをヘッダーファイルで定義することをお勧めします(その形式のパーサーを作成している場合)。

ヘッダーファイルに入力する必要がある関数は何ですか?
禁止すべき機能は何ですか?

75
Moshe Magnes

ヘッダーに挿入するもの:

  • ヘッダーがソースファイルに含まれている場合にヘッダーをコンパイル可能にするために必要な#includeディレクティブの最小セット。
  • 共有する必要があり、プリプロセッサを介してのみ実行できるもののプリプロセッサシンボル定義。 Cでも、プリプロセッサシンボルは最小限に抑えるのが最善です。
  • 構造体定義、関数プロトタイプ、およびヘッダー本体のグローバル変数宣言をコンパイル可能にするために必要な構造体の前方宣言。
  • 複数のソースファイル間で共有されるデータ構造と列挙の定義。
  • その定義がリンカーに表示される関数と変数の宣言。
  • インライン関数定義ですが、ここで注意してください。

ヘッダーに含まれないもの:

  • 不要な#includeディレクティブ。これらの不必要なインクルードは、再コンパイルする必要のないものの再コンパイルを引き起こし、システムがコンパイルできないようにすることもあります。ヘッダー自体が他のヘッダーファイルを必要としない場合は、ヘッダー内のファイルを#includeしないでください。
  • プリプロセッサ以外の何らかのメカニズム、任意のメカニズムによって意図が達成される可能性のあるプリプロセッサシンボル。
  • たくさんの構造定義。それらを別々のヘッダーに分割します。
  • 追加の#includeを必要とする、変更される可能性がある、または大きすぎる関数のインライン定義。これらのインライン関数は、ファンアウトがあってもほとんどないはずです。ファンアウトがある場合は、ヘッダーで定義されているものにローカライズする必要があります。

#includeステートメントの最小セットを構成するものは何ですか?

これは重要な質問です。 TL; DR定義:ヘッダーファイルには、で直接使用される各型を直接定義するか、問題のヘッダーファイルで使用される各関数を直接宣言するヘッダーファイルを含める必要がありますが、それ以外は含めないでください。ポインターまたはC++参照型は、直接使用としては認められません。前方参照が推奨されます。

不要な#includeディレクティブを配置する場所があり、これは自動テストです。ソフトウェアパッケージのすべてのヘッダーファイルについて、以下を自動的に生成してコンパイルします。

#include "path/to/random/header_under_test"
int main () { return 0; }

コンパイルはクリーンである必要があります(つまり、警告やエラーがないこと)。不完全な型または不明な型に関する警告またはエラーは、テスト中のヘッダーファイルに#includeディレクティブが欠落しているか、転送宣言が欠落していることを意味します。よく注意してください:テストに合格したからといって、最低限のことは言うまでもなく、#includeディレクティブのセットで十分であるとは限りません。

60
David Hammen

すでに言われていることに加えて。

Hファイルには常に次のものが含まれている必要があります。

  • ソースコードのドキュメント!!!少なくとも、関数のさまざまなパラメーターと戻り値の目的は何ですか。
  • ヘッダーガード、#ifndef MYHEADER_H #define MYHEADER_H ... #endif

Hファイルには以下を含めないでください。

  • 任意の形式のデータ割り当て。
  • 関数の定義。インライン関数は、まれな例外である場合があります。
  • staticというラベルの付いたもの。
  • Typedef、#defines、またはアプリケーションの他の部分とは関係のない定数。

(また、どこでも定数でないグローバル/外部変数を使用する理由は決してないと私は言いますが、それは別の投稿のための議論です。)

16
user29079

ヘッダーファイルの構成は次のとおりです。

  • タイプと定数の定義
  • 外部オブジェクト宣言
  • 外部関数宣言

ヘッダーファイルには、オブジェクト定義を含めないでください。型定義とオブジェクト宣言のみを含めてください。

4
theD

決して絶対とは言わないでしょうが、データとコードが解析されるときに生成されるステートメントは.hファイルに含めないでください。

マクロ、インライン関数、テンプレートはデータやコードのように見えますが、解析時にコードを生成するのではなく、使用時にコードを生成します。これらの項目は、複数の.cまたは.cppで使用する必要があることが多いため、.hに属します。

私の見解では、ヘッダーファイルには、対応する.cまたは.cppへの最小限の実用的なインターフェイスが必要です。インターフェイスには、#defines、クラス、typedef、構造体定義、関数プロトタイプ、およびグローバル変数の優先度の低いextern定義を含めることができます。ただし、宣言が1つのソースファイルでのみ使用されている場合は、おそらく.hから除外し、代わりにソースファイルに含める必要があります。

一部は同意しないかもしれませんが、.hファイルの個人的な基準は、コンパイルできるようにする必要がある他のすべての.hファイルを#includeすることです。場合によっては、これは多くのファイルになる可能性があるため、クラスへの前方宣言などの外部依存関係を減らす効果的な方法がいくつかあり、インクルードファイルの大きなツリーを含めることなく、クラスのオブジェクトへのポインターを使用できます。

4
DeveloperDon

解析時にデータとコードを生成するステートメントは、.hファイルに含めることはできません。私の観点から言えば、ヘッダーファイルには、対応する.cまたは.cppへの最小限の実用的なインターフェイスのみを含める必要があります。

0
Ajay Prasad