• ベストアンサー

ヘッダのinclude順

ヘッダにヘッダをincludeせず include順でカバーする場合と、 必要なヘッダはヘッダにincludeする という方法があると思いますが この違いはなんでしょうか? 上記の方法でも結局ヘッダの変更で影響のあるcppファイルは コンパイルする必要があるのでどちらも同じ気がするのですが 何か違い、あるいは推奨する理由はありますか?

質問者が選んだベストアンサー

  • ベストアンサー
  • cascade
  • ベストアンサー率24% (35/144)
回答No.2

どちらの方法でも同じですね。でも利点で考えれば下のようになると思います。 前者はソースファイル上にincludeしているヘッダファイルの一覧が見えて どのヘッダファイルを参照しているか一目瞭然になります。 後者はヘッダファイルのパッケージ化(カプセル化?)を行うことになるので、 ある関数を使うときはこれさえあればいいといった感じになります。 どちらを選択するかは作り手の好みの問題じゃないでしょうか。 私なら… ソース上にincludeがたくさん並んでも煩雑になるような気がするので 後者が好きかなあ。

furyfox
質問者

お礼

ご回答有り難うございます。 私も基本は後者なのですが、古参の方は前者が多い気がします。 好みの問題なのですかね。 私もソースを流用する点においては後者だと思います。 >前者はソースファイル上にincludeしている >ッダファイルを参照しているか一目瞭然になります。 なるほど。納得しました。

その他の回答 (7)

  • ency
  • ベストアンサー率39% (93/238)
回答No.8

複数の人たちでひとつのプログラムを作るような場合には、ひとつに機能に対して公開ヘッダを一つ作ることが多いですよね。 その公開ヘッダには、必要なヘッダファイルがすべてインクルードしてあって、それだけインクルードすればその使いたい機能を使うことができるわけです。 ただ、そこで必要のないヘッダファイルまでインクルードしないようにしましょう。 そういう意味じゃ、なんでもかんでもインクルードすれば良いというわけじゃなくて「必要最小限」である必要があります。 というわけで、私は後者派ですね。 前者のほうは…すみません、使用しないのでメリットがいまいちよくわかりません。

furyfox
質問者

お礼

ご回答ありがとうございます。

  • rinkun
  • ベストアンサー率44% (706/1571)
回答No.7

絶対にヘッダファイルをインクルードする必要がある依存関係としては、継承があります。こればっかりはどうしようもない。あとはメンバで(ポインタでなく)実体を宣言している場合。 他は何があったかな。

furyfox
質問者

お礼

何度も回答いただき有難うございます。 大変参考になりました。

  • yasuch
  • ベストアンサー率41% (27/65)
回答No.6

No.4です。 --- a.h --- class B; class A { int funcA(B* pB); : } こう定義しておいて、funcAを使う必要がある場合だけ ソースから b.h をインクルードするようにすれば a.h が先だろうと b.h が先だろうと関係なるので 極力インクルード順に依存しないように定義して 必要なヘッダをソースからインクルードした方が 良いと言いたかったのですが、 質問の読み返してみると、質問の意図と 全然違いましたね。 (^_^)

furyfox
質問者

お礼

yasuchさん、rinkunさん ご回答有り難うございます。 ヘッダにヘッダが必要な状況というのは class A { int funcA(B* pB){ pB->funcB(); } }; って感じでヘッダにfuncAの定義も書いちゃうとb.hが必要ですね。 でも個人的にこの場合はあまりa.hにb.hはincludeしたくないので (コンパイルの影響範囲がでかくなるため) a.cppに書いてb.hをincludeするかも。 (ただinline展開されないだろうから、オーバーヘッドはでかくなる?) あとa.hにb.hが必要なのってBのサイズを知る必要がある場合でしょうか。 int funcA(B *pB)では無く int funcA(B b) なら必要ですよね。

  • rinkun
  • ベストアンサー率44% (706/1571)
回答No.5

No.4さんの例は不適当だと思うな。これはそもそもインクルードする必要がない例だからインクルード順に配慮する必要ないし。 元の質問と対応づけるなら、 --- a.h --- class A { int funcA(B* pB); : } --- として.cxxファイルでa.hを読み込む前に前方参照(またはb.hのインクルード)をするか、 --- a.h --- class B; class A { int funcA(B* pB); : } --- とするかの選択になると思う。 この事例なら前者にする奴はまずいないと思うけど。

  • yasuch
  • ベストアンサー率41% (27/65)
回答No.4

私はモジュール間の依存関係を抑える為に、前者を使いますよ。 依存関係が密になると、コンパイルすらできなくなりますから。 下記の場合でも、インクルードせずに前方参照にしておけば 問題ありません。 --- a.h --- #include "b.h" class A { int funcA(B* pB); : } --- b.h --- #include "c.h" class B { public: int funcB(C* pC); : } --- c.h --- #include "a.h" class C { public: int funcC(A* pA); : }

  • rinkun
  • ベストアンサー率44% (706/1571)
回答No.3

基本的に昔のやり方だと思いますよ、ヘッダを並べるのは。 昔は、二重インクルード防止策も一般的じゃなかったし、一回コンパイラを走らせると1時間なんてこともあったのでちょっとの効率差も大事だし、依存関係も自動抽出できなかったのでヘッダを並べた方が分かりやすかったんでしょう。 今では入れ子インクルードを忌避する理由のは、二重インクルード防止策がない古いヘッダを読み込むとトラブることくらいかと。

  • rinkun
  • ベストアンサー率44% (706/1571)
回答No.1

ヘッダからヘッダをインクルードする方がプログラムを読む方には分かりやすいですし、新規にプログラムファイルを追加する場合にもインクルードするファイルと順序を気にする必要性がなく楽ですね。 ただしヘッダからヘッダをインクルードする場合、ヘッダファイルで二重インクルードを防止する対策を取っていないとエラーが出やすくなります。また二重インクルード対策を取っていてもインクルードするファイルが増えるのでコンパイルが遅くなります。 ちなみに自分は、ヘッダからヘッダをインクルードする方針で全体を統一しておく方針で書きます。

furyfox
質問者

お礼

ご回答有り難うございます。 前者を使う人もいるので前者に何かメリットが あるのかなと思った次第です。 1.E-10秒ぐらいはコンパイルが早くなるって感じでしょうか。

関連するQ&A

  • ヘッダーファイルのインクルード

    VC++6.0です。 ヘッダーファイルをincludeしていいかどうかは どのように決まるのでしょうか? classは、appとhogeの1種類があるとして、 app.h、app.cppとhoge.cpp、hoge.hの4つのファイルがあるとします。 1)appによるhogeのメンバの操作があって、その逆は無い場合 2)hogeもappのメンバを操作する場合 のそれぞれで教えてください。 最初、私は、そのclass内で別のclassのメンバ関数を 呼ぼうと呼ぶまいとincludeしてもかまわないと思っていました。 しかし、自分の作ったプログラムを検討したところ 1)の場合で、hogeのヘッダーに #include "app.h"と入れるとエラーになります。 hogeのcppファイルに#include "app.h"と入れてもエラーになります。

  • C++のヘッダーについて

    C++のプログラミングをしています そこで出てきた問題なのですが・・・ class Aのヘッダファイルa.hをほかのcppファイルにインクルードすると、 error C4430: 型指定子がありません - int と仮定しました。メモ: C++ は int を既定値としてサポートしていません error C2146: 構文エラー : ';' が、識別子 'test' の前に必要です。 とほかのヘッダファイルでコンパイルエラーがでます ヘッダファイルをインクルードしたときのみこのエラーがでて困っています。 解決法や、ヒントになりそうな事例を知りませんでしょうか?

  • ヘッダのインクルード時のエラー

    初歩的な質問で恐縮です。 以下のようなファイルの構成でc++のプログラムを組んでいます。 <header.h> class H { public: virtual void func() = 0; }; <fileA.cpp> #include "header.h" class A : public H { public: void func() {} }; <fileB.cpp> #include "header.h" class B : public H { public: void func() {} }; <main.cpp> #include "fileA.cpp" #include "fileB.cpp" int main() { A a; B b; a.func(); b.func(); return 0; } これをビルドしようとすると、「クラス"H"を再定義しようとしています」とエラーが出てコンパイルができません。理屈は分かるのですが、これの対処方法が分かりません。この場合、header.hはJAVAにおけるInterfaceのような役割としてそれを使うfileA.cpp、fileB.cppの両者にインクルードしておきたいのです。これはどのようにして対処すべきなのでしょうか?

  • ヘッダーファイルでは、他のヘッダーファイルをインクルードできないのか

    Javaを仕事で使っています。 最近趣味でC++を始めました。色々形式の違いに戸惑っています。 C++では関数を宣言しなければならないので、クラス名と同じヘッダーファイルにそのクラスで使う関数を宣言して、それをインクルードしています。 そこで今、壁にぶちあたりました。 あるクラス(仮にFooとします)の関数で、他のクラス型(Hogeとします)を引数に取りたいので、ヘッダーファイルにそれを宣言しようとしているのですが、コンパイルエラーになってしまいます。 Foo.hは以下のような感じ。 #include Hoge.h 中略 GetHoge(Hoge hoge); コンパイルエラーでは error C2011: 'Hoge' : 'class' 型の再定義 などと言われます。 クラスとその同名のヘッダーファイル、という形式を変えずに 他のクラス型を引数にとる関数を作るには、どうしたらよいのでしょうか? C++に関しては全くの素人です。詳しい方、ご教示願います。

  • ヘッダファイルの2重のインクルードについて

    ある書物に「ヘッダファイルを複数回インクルードすると、それを”再定義”することによるエラーになる」と書いてありますたが、以下のようなヘッダファイルを作りそれを数回インクルードしても何ら異状が無くコンパイルできました。 math.h→ヘッダファイル名 #define max(a,b)  ((a)>(b)?(a):(b))→ヘッダファイルの内容 c ファイル #include<stdio.h> #include"math.h"←複数回インクルード #include"math.h"←複数回インクルード int main(void){ int x=1,y=2; printf("max(x,y)=%d\n",max(x,y)); return 0; } 環境としては、RedHat Linuxでviです。 何ゆえ、エラーにならないのか良く解りません。 宜しくお願いします。

  • なぜ、C++の標準ヘッダをインクルードするとき拡張子をつけないのか。

    なぜ、C++の標準ヘッダをインクルードするとき拡張子をつけないのか。 そもそもiostreamなどは拡張子をもっているのですか? 拡張子はあるけれどインクルードするときに付けてないだけとか?だとしたら、同じファイル名で拡張子の違いで判別できないですよね?a.hとa.hppがあったら#include <a>じゃわからないって意味。 自分でヘッダーファイルを作る場合はどのようにすればいいのでしょうか? 自分で作ったヘッダーファイルも標準ヘッダの様に拡張子を付けないでインクルードすることができますか?そういった事はするべきではないのでしょうか? この拡張子をつけないというのはC++の標準ヘッダだけ特別仕様とか? Cと同じように.hでヘッダーファイル作って#include "a.h"とかにしておけばいいのかなー?? 詳しい方、わかりやすく説明して頂けないでしょうか。よろしくお願いします。

  • 自作したヘッダファイルをインクルードするには

    自作したヘッダファイルをインクルードするには 自作したヘッダファイルを半角スペースを含むフォルダを指定する時、 何かエスケープシーケンス文字が必要でしたでしょうか?ド忘れしてしまいました… 例えば、Program Filesの直下に入れた自作ヘッダファイルa.h(まず考えられないとは思いますが…)を インクルードしたい時、 #include "C:\\Program Files\\a.h" でいいんですよね?

  • ヘッダのinclude LSI試食版

    はじめまして。 よろしくお願いします。 コンパイラー:LSI C-86 Ver.3.30 試食版 OS:Windows Me includeフォルダの中にあるヘッダ以外に 新しいヘッダnew.hを \lsic330c\INCLUDEフォルダの中にいれて 1.cというファイルで #include<new.h> としてみたのですが、 コンパイル時にlcc 1.cとしてみても 1.c 1: ファイル new.hがオープンできない(No such file or directory) というエラーがでてしまいます。 よろしくお願いします。

  • Linux C言語開発 インクルードについて

    C言語開発初心者です。 LinuxでC言語開発をするにあたり、どのディストリビューションにしても インクルードしたいヘッダファイルが既定の場所には無く別の場所にカーネルのバージョンごとに保存されているようなのです。 このままコンパイルを試みるとインクルードファイルが存在しませんとエラーが返ります。 既定のヘッダファイルの保存場所にはC言語開発に必要なヘッダファイルが存在しませんので、この問題を皆さんはどのように解決しておりますか?どなたかご教授お願いいたします。 C言語でincludeする場所は<>でくくった場合 /usr/include/ 以下を参照する設定になっていると思うのですが、 例えばmodule.h やinit.h などの開発用ヘッダファイル?を探してみると /usr/include/linux/ には存在せず、 find / -name module.h と入力して検索してみると /usr/src/kernels/2.6.32-131.21.1.el6.i686/include/linux/module.h と別な場所にあります。 ネットであれやこれや調べてみても コンパイル時にincludeの参照先を指定する方法はあるようなのですが、 コンパイルする度にいちいち指定するのは面倒だと思います。(gcc -I) かといって開発しているカレントディレクトリにヘッダファイルをコピーしても includeするヘッダファイルが別のヘッダファイルを参照することもあるようなので、 あまり現実的ではないようです。 一番安全な方法としてincludeする参照先が環境変数か何かで追加及び変更するのではないかと思います。 試してみましたがenvコマンドで表示されるOSの環境変数とは別のもののようなのです。 環境変数 C_INCLUDE_PATH とはどのようにして変更・追加するのでしょう? また、上記の方法以外で良い方法がございましたらそれでもかまいません。 よろしくお願いいたします。 開発環境 ・OS centos6 ・以下のパッケージはインストール済み kernel-headers-2.6.32-131.21.1.el6.i686 kernel-devel-2.6.32-131.21.1.el6.i686 make-3.81-19.el6.i686 gcc-4.4.5-6.el6.i686 ・GUI開発環境 netbeans ・uname -r 実行結果 2.6.32-131.21.1.el6.i686

  • VC++6.0でのインクルード

    VC++初心者です。 環境はVC++ on win2kなのですが、 ヘッダファイルを別のファイルにしてコンパイルしたいのですが、できません。 test.cppの中身 #include <iostream> #include <string> #include <stdio> ・・・* #include "kneko.h" using namespace std; int main() { kneko x("tama"); x.naku(); } kneko.hの中身 #ifndef __kneko_h #define __kneko_h class kneko { string name; public: kneko(){}; kneko(string n){ name=n; } void setname(string n){ name=n; } void naku() const { cout <<"My name is"<<"name"<<"."endl; } }; #endif この2つを同じディレクトリに入れて、 ビルド→コンパイルすると、*のところで 「インクルードファイルがオープンできません。」 というエラーが出ます。 ためしに*の行を削除すると、エラーが8つぐらい出てきます。 どうやらヘッダファイルを読み込めていないようです。 インクルードの書式が間違っているのでしょうか?

専門家に質問してみよう