2011-07-05 3 views
2

ヘッダーファイルに#includeがありますか?ヘッダーファイルに含まれています

私は一般に、この種の階層的なインクルードが悪いと考えています。あなたはこれを持って言う:

がfoo.h:

#include <stdio.h> // we use something from this library here 
struct foo { ... } foo; 

main.cの

#include "foo.h" 
/* use foo for something */ 
printf(...) 

日のmain.cの実装の変更、そしてあなたは、もはや、コンパイルが意志がfoo.hを使用していませんあなたは手で<stdio.h>を追加する必要があります。 、

がfoo.h

// Warning! we depend on stdio.h 
struct foo {... 

main.cの

#include <stdio.h> //required for foo.h, also for other stuff 
#include "foo.h" 

とするとき、あなたがfooの使用を停止し、それが何を壊していない取り除くが、stdio.hの意志を削除:これを持つ対

foo.hを破る。

#hファイルから#includesを含める必要がありますか?

+0

可能重複[C++用の標準の#include規則はありますか?](http://stackoverflow.com/questions/691079/is-there-a-standard-include-convention-for-c)。これはC++ではなくCですが、原則は同じです。そこには良いアドバイスがたくさんあります。 http://stackoverflow.com/questions/181921/your-preferred-c-c-header-policy-for-big-projectsは別です。 –

答えて

4

あなたは、このテーマに関する2つの主な哲学について概説しました。

私の意見では、ヘッダーは可能な限り自己完結型でなければならないと私は考えています。私はfoo.hのすべての依存関係を知ってそのヘッダを使用できるようにする必要はありません。私はまた、特定の順序でヘッダーを含める必要がありません。

しかし、foo.hの開発者は、できるだけ依存性のないものにする責任を負います。たとえば、foo.hヘッダーは、可能であればstdio.hに依存しないように書かれていなければなりません(フォワード宣言を使用するとそれに役立ちます)。

C標準では、標準ヘッダーに別の標準ヘッダーを含めることは禁じられていますが、C++標準では使用できません。したがって、あるC++コンパイラー・バージョンから別のC++コンパイラー・バージョンに移動するときに記述した問題を見ることができます。たとえば、<vector>を含むMSVCでは、<iterator>が発生しますが、MSVC 2010ではこれ以上発生しません。したがって、先にコンパイルされたコードは、具体的には<iterator>を含める必要があります。

しかし、C標準が第2の哲学を支持しているように見えるかもしれませんが、ヘッダーは別のものに依存せず、任意の順序でヘッダーを含めることができます。だから、両方の世界のベストを得ることができますが、Cライブラリの実装者にとっては煩雑です。これを行うには、いくつかのフープを実行する必要があります(特に、NULLまたはsize_tのようないくつかのヘッダーのいずれかを介して取り込むことができる定義をサポートするため)。私は、C++標準を策定した人々が、偽装者にはその複雑さがもはや合理的ではないと判断したと思います(C++ライブラリの実装者が「抜け穴」をどの程度活用しているか分かりません。技術的に要求されていなくても)。

+0

''がイテレータで動作するメソッドを宣言している場合、なぜ ' 'を引っ張ってはならないのですか?なぜユーザーはこれを実行する必要がありますか?ユーザーが ''の後に '' *を入力した場合はどうなりますか? –

+0

私はおそらく、「これを引き締める」と言ってはいけない - 私は 'は'から '' に引っ張っていなかった場合(それはおそらく最高だっただろう、これは必ずしもユーザーにとって良いことだったことを意味するというわけではありませんでした開始)。 ''の後(またはそれ以前)に ''を引っぱっても何の問題もありません。既に含まれている場合は、 ' 'に含まれるインクルードガードが2度目に問題を起こさないようにします。 –

+1

しかし、それは私を気にことだ:なぜ '' に引っ張ることをユーザーに要求し、 '' 前にそれを行う、だけではなく、「'の#include は'だけで動作します」というのは?これは意図的に複雑さを増やし、何らかの「純度」という名前でバグを導入するようなものです。 –

2

最初に、stdioの場合、"foo.h"に頼ってはなりません。何かを何度か入れても害はありません。
また、おそらくfoo。 hは実際にはstdioを必要としません。より具体的には、foo.c(実装)にはstdioが必要です。

短い話ですが、誰もが必要としているものを含めて、include guardsに依存する必要があると思います。コードファイルは、ヘッダを必要としない場合

+0

'stdio'は任意の選択ですが、struct {foo}は' stdio'で定義された型を使うことができます。 main.cとfoo.cの両方にstdio.hとfoo.hを含める必要があります。 – Tordek

+0

一般的な例は、 'size_t'型を必要とするヘッダです。 – caf

0

ヘッダファイルは、特定のヘッダを必要とする場合は、ヘッダファイルに追加

#ifndef HEADER_GUARD_YOUR_STYLE 
#define HEADER_GUARD_YOUR_STYLE 

#include <stdio.h> /* FILE */ 
int foo(FILE *); 

#endif /* HEADER GUARD */ 

、追加しないでください、それ

/* #include <stdio.h> */ /* removed because unneeded */ 
#include <stddef.h> /* NULL */ 
#include "header.h" 
int main(void) { 
    foo(NULL); 
    return 0; 
} 
0

なぜヘッダーに対応する* .cファイルの内容を#includeしないでください。

1

数百または数千のヘッダファイルを含むプロジェクトに入ると、これは許されません。私は"MyCoolFunction.h"というヘッダファイルを持っていて、MyCoolFunction()のプロトタイプを含んでおり、その関数は構造体へのポインタをパラメータとして受け取ります。 MyCoolFunction.hには、必要なものがすべて含まれていて、.hファイルを調べずにその機能を使用することができると仮定することができます。

2

私の一般的な推奨事項は以下のとおりです。

  • ファイルがすべき#include何が必要。
  • #includeに何か必要なものはありません。
  • #include何か他のものがそれを望むかもしれないので、それは必要ではありません。

本当のテストはこれです:あなたは、任意の単一の#includeからなるソースファイルをコンパイルし、「何のmain()がありません」を超えてエラーや警告を取得しないことができるはずです。このテストに合格すれば、何も問題なくファイルを#includeできるようになります。私はこれをテストするために使用する「hcheck」と呼ばれる短いスクリプトを書いている:

#!/usr/bin/env bash 
# hcheck: Check header file syntax (works on source files, too...) 
if [ $# -eq 0 ]; then 
    echo "Usage: $0 <filename>" 
    exit 1 
fi 

for f in "[email protected]" ; do 
    case $f in 
     *.c | *.cpp | *.cc | *.h | *.hh | *.hpp) 
      echo "#include \"$f\"" > hcheck.cc 
      printf "\n\033[4mChecking $f\033[0m\n" 
      make -s $hcheck.o 
      rm -f hcheck.o hcheck.cc 
      ;; 
    esac 
done 

私はこのスクリプトをよりよく行うことができることをいくつかのものがあると確信しているが、それは良い出発点でなければなりません。

これがあまりにも多く、ヘッダーファイルにほとんど常に対応するソースファイルがある場合は、関連するヘッダーがソースファイルの最初の#includeであることを要求することです。たとえば、次のように

がfoo.h:

#ifndef Foo_h 
#define Foo_h 

/* #includes that Foo.h needs go here. */ 

/* Other header declarations here */ 

#endif 

がFoo.c:

#include "Foo.h" 
/* other #includes that Foo.c needs go here. */ 

/* source code here */ 

また、これは他の人が言及したことがfoo.hで "警備員を含める" を示しています。

#include "Foo.h"を最初に入力すると、Foo.hはその従属性が必要です。そうしないと、コンパイルエラーが発生します。

関連する問題