私はいくつかの非常に大規模なシステムを使用しており、必要な注文を見たことはありませんでしたが、最近見つけました。STL または STD ライブラリ、さらには Boost にも、特定のインクルードを特定の順序で配置する必要があるケースはありますか?
13 に答える
STL または STD ライブラリ、さらには Boost にも、特定のインクルードを特定の順序で配置する必要があるケースはありますか?
標準の場合、答えは断固としてノーです。調べたことはありませんが、Boost にも同じことが当てはまると思います。
C標準から:
標準ヘッダーは任意の順序で含めることができます。それぞれが与えられたスコープに複数回含まれる可能性があり、含まれる効果が
<assert.h>
定義に依存することを除いて、1回だけ含まれることと同じ効果がありますNDEBUG
(7.2を参照)。
C++ 標準にも同様の表現があります。
私の好みは、ヘッダーに独自の依存関係を含めることですが、これは「無駄」であると信じている人々と協力してきました。私の意見では、ヘッダーに依存関係を含めないことは、価値のない初期の最適化です。
これは間違いなく悪い設計のように聞こえます。どういうわけか特定の順序が必要な場合、ライブラリは正しい順序で他のヘッダーを含む1 つのヘッダーを提供する必要があります。
ブーストと STL に関する限り、私はまだこの状況に遭遇したことがないと確信しています。
特定の順序でインクルードを指定する必要があるということは、ほとんどの場合、設計上の問題を示していました。これを誤って行う可能性を減らす 1 つの方法は、クラスのヘッダー ファイルを実装ファイルの最初の #include としてインクルードすることです。
// A.cpp
#include "A.h"
#include "boost/shared_ptr.hpp"
#include <vector>
class A {
// ...
};
このように、たとえば、Ah が適切な #include なしでベクターを使用すると、A.cpp はコンパイルされません。
これをどこで拾ったか覚えていません。それは、Lakos の「Large Scale C++ Design」(実際に更新を使用できる素晴らしい本) からのものである可能性があります。
STL または STD ライブラリ、さらには Boost にも、特定のインクルードを特定の順序で配置する必要があるケースはありますか?
私はこれに出くわしたことはありません。もしそうなら、著者にできるだけ早く通知する必要があります. そして、そうそう、それは非常に悪いデザインです。
それは「悪いこと」です。より良い方法が言及されています。しかし、詳しく説明します。
//a.h #ifndef _A_H_ #define _A_H_ //... code ... #endif // ----------------- //b.h #ifndef _B_H_ #define _B_H_ #include a.h //... code ... #endif // ----------------- //main.cpp Try 1 #include "b.h" //<- okay! b includes a, then does b // ----------------- //main.cpp Try 2 #include "a.h" //<- includes a #include "b.h" //<- okay! b includes a, but skips redefining it, then does b // ----------------- //main.cpp Try 3 #include "b.h" //<- b includes a, then does b #include "a.h" //<- okay! a skips redefining itself! // ----------------- //main.cpp Try 4 #include "a.h" //<- fail! b is not included anywhere =(
プロジェクト レベルの互換性ヘッダー (compat.h など) を.c/.cpp ソース ファイルの最初のヘッダーとして含めることは一般的な手法です。標準ヘッダーのその後の動作。
この使用法を最初に目にしたのは、かなり前に内部ライブラリの有能なプログラマーでした。後で、'git' (悪名高い dvcs) プロジェクトでもこの手法が使用されているのを見ました。
ヘッダーに含まれる関数やクラス (Ah など) が別のヘッダー (Bh など) で定義された関数やクラスに依存している場合、最初のヘッダーのユーザーを強制するのではなく、後者を最初のヘッダーに含めることを好みます。 1 つは特定の順序で両方を含めます。
はい:
// A.h
#pragma once
// or the #ifndef trick
#include "B.h"
// A.cpp
#include "A.h"
いいえ:
// A.h
#pragma once
// or the #ifndef trick
//#include "B.h"
// A.cpp
#include "B.h"
#include "A.h"
ヘッダーをアルファベット順に含めるのが好きです。これにより、既に行ったことを簡単に確認できます。
順序が間違っているためにライブラリが機能しない場合は、ライブラリが壊れているため、順序に依存しないように修正する必要があります。
はい、C ++にインクルードするために特定の順序を要求することは、ライブラリ/ヘッダーの設計が悪いことを示しています。
ただし、前方宣言では、クラスを完全に使用するために複数のファイルを含める必要がある場合があります。以下の例を参照してください。
//ああ
class B; // forward declaration
class A
{
void doStuff(const B& b);
};
// main.cpp
#include <A.h>
#include <B.h>
int main()
{
A a;
B b;
a.doStuff(b);
}
私の知る限りではありません。それはかなり悪い習慣です。ただし、最近、コードに Windows ヘッダーと奇妙なインターフェイスが含まれていることに遭遇しました。