質問

ヘッダー/ cppファイルでヘッダーを宣言する順序は?明らかに、後続のヘッダーに必要なものはより早く、クラス固有のヘッダーはヘッダースコープではなくcppスコープにある必要がありますが、設定順序の規則/ベストプラクティスはありますか?

役に立ちましたか?

解決

ヘッダーファイルには、コンパイル可能にするためにすべてのヘッダーを含める必要があります。また、ヘッダーの代わりに前方宣言を使用することを忘れないでください。

ソースファイル内:

  • 対応するヘッダーファイル
  • 必要なプロジェクトヘッダー
  • サードパーティのライブラリヘッダー
  • 標準ライブラリヘッダー
  • システムヘッダー

この順序で、独自にライブラリを含めるのを忘れたヘッダーファイルを見逃すことはありません。

他のヒント

グッドプラクティス:すべての.hファイルには、その.hが最初に含まれる.cppが必要です。これは、どの.hファイルでも最初に置くことができることを証明しています。

ヘッダーに実装が不要な場合でも、その.hファイルのみを含む.cppを作成します。

これは、あなたが質問に自由に答えることができることを意味します。どの順序でそれらを含めてもかまいません。

さらに優れたヒントについては、次の本を試してください:大規模C ++ソフトウェア設計-とても高価なのは残念ですが、実際にはC ++ソースコードレイアウトのサバイバルガイドです。

ヘッダーファイルでは、最初に標準ヘッダーを配置し、次に自分のヘッダーを配置する傾向があります(両方のリストはアルファベット順になっています)。実装ファイルでは、対応するヘッダー(存在する場合)を最初に配置し、次に標準ヘッダーと他の依存関係ヘッダーを配置します。

順序は、マクロと#defineを大いに活用する場合を除き、ほとんど重要ではありません。その場合は、定義したマクロが以前に含まれていたマクロを置き換えないことを確認する必要があります(もちろん、必要な場合を除きます)。

この声明について

  

後続のヘッダーに必要なものは、より早くする必要があります

ヘッダーは、その前に含まれている他のヘッダーに依存すべきではありません!ヘッダーが必要な場合は、ヘッダーのみが含まれます。ヘッダーガードにより、複数のインクルードが防止されます。

#ifndef FOO_HEADER_H
#define FOO_HEADER_H
...
#endif

編集

この回答を書いてから、コード内のincludeディレクティブの順序を変更しました。現在、私は常に標準化の昇順でヘッダーを配置しようとしているので、私のプロジェクトのヘッダーが最初に来て、サードパーティのライブラリヘッダー、標準ヘッダーの順に続きます。

たとえば、私のファイルの1つが、私が書いたライブラリ、Qt、Boost、および標準ライブラリを使用する場合、次のようにインクルードを注文します。

//foo.cpp
#include "foo.hpp"

#include <my_library.hpp>
// other headers related to my_library

#include <QtCore/qalgorithms.h>
// other Qt headers

#include <boost/format.hpp> // Boost is arguably more standard than Qt
// other boost headers

#include <algorithms>
// other standard algorithms

それを行う理由は、独自のヘッダーで欠落している依存関係を検出するためです。たとえば、my_library.hppstd::copyを使用しますが、<algorithm>は含まれないと仮定しましょう。 foo.cppの<=>の後にそれを含めると、この欠落した依存関係は見過ごされます。それどころか、私が提示した順序では、コンパイラは<=>が宣言されていないことを不平を言うので、<=>を修正できます。

各<!> quot; library <!> quot;グループでは、インクルードディレクティブをアルファベット順に並べて、より簡単に見つけられるようにしています。

サイドノートでは、ヘッダーファイル間の依存関係を最大限に制限することもお勧めします。ファイルには、できる限り少ないヘッダー、特にヘッダーファイルを含める必要があります。実際、追加するヘッダーが多いほど、何かが変更されたときに、より多くのコードを再コンパイルする必要があります。これらの依存関係を制限する良い方法は、前方宣言を使用することです。これは多くの場合、ヘッダーファイルで十分です(いつ前方宣言を使用できますか?)。

Google C ++スタイルガイド、名前、インクルードの順序

  

dir / foo.ccの主な目的はdir2 / foo2.hの内容を実装またはテストすることで、インクルードを次のように順序付けます。

     
      
  • dir2 / foo2.h(優先場所<!>#8212。以下の詳細を参照)。
  •   
  • Cシステムファイル。
  •   
  • C ++システムファイル。
  •   
  • 他のライブラリの.hファイル。
  •   
  • プロジェクトの.hファイル。
  •   

以前はアルファベット順に並べていました(見つけやすい)

<!> quot; how <!> quot;明らかではありませんが、<!> quot; what <!> quot;です。 あなたの目標は、ヘッダーファイルをインクルードする順序が重要ではないことを確認することです(つまり、<!> quot; NEVER!<!> quot;を意味します)。

良いヘルプは、ヘッダーファイルを1つだけ含むcppファイル(ヘッダーファイルごとに1つ)を作成するときにヘッダーファイルがコンパイルされるかどうかをテストすることです。

.cppファイルの場合は、クラスのヘッダーまたは最初に実装するものを含める必要があります。そのため、このヘッダーにインクルードが欠落しているケースをキャッチします。その後、ほとんどのコーディングガイドラインには、最初にシステムヘッダー、次にプロジェクトヘッダー、たとえば Google C ++スタイルガイド

これは依存関係の問題であり、ヘッダーに何を配置するかに大きく依存します。実際、これについては非常に悪名高く、最小化してインクルードを厳密に保つことができますが、最終的にはインクルージョンガードを使用したいシナリオに陥ります。

#ifndef MY_HEADER_H
#define MY_HEADER_H
//...
#endif

問題は最初はそれほど明白ではありませんが、ソフトウェアの複雑さが増すにつれて依存関係も大きくなります。あなたはうまくやることができ、それについて賢くすることができますが、大規模なC ++プロジェクトは一般的にインクルードでいっぱいです。試すことはできますが、できることはそれだけです。だから、勤勉になり、あなたのインクルードについて考えてください、はい!しかし、ある時点で確実に周期的な依存関係があることになるため、包含ガードが必要です。

ヘッダーに他のヘッダーが必要な場合は、ヘッダーにそれらを含めるだけです。

ポインターまたは参照を渡し、可能な場所を前方宣言するようにコードを構造化してみてください。

実装では、それを定義するヘッダーを最初にリストする必要があります(Visual Studioでpchを使用している場合はstdafxが最初に移動します)。

通常、必要に応じてリストします。

次の規則が最も便利であることがわかりました。

module.cpp:

// this is the header used to trigger inclusion of precompiled headers
#include <precompiled.h> 
// this ensures that anything that includes "module.h" works
#include "module.h"
// other headers, usually system headers, the project

重要なことは、モジュールのヘッダーを最初のプリコンパイルされていないヘッダーにすることです。これにより、<!> quot; module.h <!> quot;予期しない依存関係はありません。

ディスクアクセス時間が遅い大規模なプロジェクトで作業している場合、このスタイルを使用してビルド時間を短縮できます:

module.cpp:

// this is the header used to trigger inclusion of precompiled headers
#include <precompiled.h> 
// this ensures that anything that includes "module.h" works
#include "module.h"
// other headers, usually system headers, the project
#if !defined _OTHER_MODULE_GUARD_
#include "other_module.h"
#endif 

#if !defined _ANOTHER_MODULE_GUARD_
#include "another_module.h"
#endif 

これは少し冗長ですが、ヘッダーが既に含まれている場合はヘッダーが検索/開かれないため、ディスクのシークを節約します。ガードチェックなしでは、コンパイラはヘッダーファイルを探して開き、ファイル全体を解析して#ifdefファイル全体を出力します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top