No.1
- 回答日時:
ヘッダファイルは、最初からある物も含めてそのファイル中で使う変数や関数、クラスにどういうものがあるのかを記述してあります。
例えばa.ccというファイルの中で作ったクラスをb.ccというファイルで使うためには、そのクラスの名前やどのように呼び出す関数があるのかがわからないとb.ccというファイルを見ただけではわかりません。そこでそのクラスの呼出方等を記述した物がヘッダでありそれを参照することによって文法的に正しいかをチェックするわけです。
No.2
- 回答日時:
aaa.c というように、単一ファイルで構成される
場合、インクルードファイルは、不要です。
aaa.c bbb.c ccc.c など、ソースファイルが複数
あるような場合、
共通する#define定義・外部変数の定義/extern 宣言
または、bbb.cに存在する関数をaaa.cで参照するよう
な場合の関数のextern宣言など、複数のソースファイ
ルで共通的な定義をする場合、インクルードファイル
を使用します。
下記URLが比較的わかりやすく書かれています。
「2.インクルード」を参照してください。
参考URL:http://www.orchid.co.jp/computer/cschool/clec10. …
No.3
- 回答日時:
あるソースファイルで定義された関数を他のソースファイルでも使いたい場合に、その宣言をヘッダファイルに記述し、それを使用したいソースファイルでインクルード(取り込み)します。
また、複数のソースファイルで共通に使用される定義は複数のソースにそれぞれ同じ定義を記述するのではなく、ひとつのヘッダに記述してそれぞれのソースファイルの先頭でインクルードします。こうすることで、定義の内容があとで変わったときなどに1箇所だけ修正すればすむようになります。
ひとによって違う部分もあるとおもいますが、わりと一般的な暗黙のマナーとして、(すべておおまかなもので厳密に守らなければいけないというようなものではない)
○ヘッダファイルはだいたいひとつのソースファイルに対し、ひとつ作成します。
ヘッダファイル名はソースファイル名と同じで、拡張子を.hにします。
○ヘッダファイルの先頭に以下のような2重インクルードを防ぐための#ifdefを定義するのが一般的です。
(HONYARARAはなんでもよいが他で使われていないことが保証されるもの。たとえばヘッダファイル名を使用)
--------------
#ifndef __HONYARARA_H__
#define __HONYARARA_H__
ここにヘッダの内容
#endif /* __HONYARARA_H__ */
--------------
同じヘッダを2回インクルードするとコンパイル時にすでに定義されています、というようなエラーになりますが、こうしておけばそれを回避できます。
○ヘッダファイルに#includeで別のヘッダをインクルードするのは[できるだけ]避けます。
もちろんそれが必要な場合もありますので禁止というわけではありません。
ヘッダにヘッダをインクルードすると、必要以上にそのヘッダを参照するソースが増えるため、たとえばあるヘッダを修正すると、本来その必要のないソースまで大量のソースを再コンパイルしてしまう羽目になりかねません。
質問者さんの立場はよくわかりませんが、これらはいまはよく意味がわからなくてもマナーとして癖にしておくとよいとおもいます。
No.4
- 回答日時:
ヘッダファイルの作り方は人によって方針が異なりますので、回答者間で矛盾した回答が得られる可能性が高いかと思います。
それを踏まえて...まず、C専用か、C++専用か、C/C++両用かによって、若干作り方が異なります。
C専用の場合、ファイル名は~.hにすることが多いかと思います。C++で使うことを想定しなくてもよいので、比較的シンプルな作りになるかと思います。
C++専用の場合、ファイル名は~.hの他、~.hppや~.hhなどが使われます。クラス指定子や、インライン関数定義、(exportがサポートされないので)テンプレート関数定義などがヘッダファイルの中で行われます。
C/C++両用の場合、基本的にはC専用と同じですが、__cplusplusマクロが定義される場合には、外部宣言をextern "C" {~}で囲んだり、マクロの使用を最小限に抑えたりと、C/C++のどちらにも通用する作り方をする必要があります。
どの場合にも共通なのは、多重インクルードを抑止するための仕組みが必要です。
#ifndef XXX
#define XXX
...
#endif
といった書き方ですが、ここで大切なのは、マクロ名XXXは下線(アンダースコア)で始めないことです。下線で始まるファイル有効範囲(C++では大域的前空間有効範囲)の識別子は処理系と標準ライブラリに予約されており、そうした識別子をマクロとして定義した場合の動作は未定義になってしまうからです。
もう一つは、(#endifの後など)ファイルの終端は必ず改行で終わることです。これも、空でないソースファイルが改行文字で終わらない場合の動作は未定義になるからです。
ヘッダファイルからヘッダファイルのインクルードについては意見が分かれるところですが、私の場合は積極的に行っています。共通する内容を複数のヘッダファイルに分散して記述すると保守性が下がることが理由です。
現在のコンパイラやPCの性能からすれば、プリプロセスに要する時間が問題になることはほとんどありませんが、どうしても気になる場合は、インクルードの際に、
#ifndef XXX
#include "xxx"
#endif XXX
とすれば、無駄な処理を最小限に抑えることができます。
No.5ベストアンサー
- 回答日時:
これまでの回答でほぼ出揃っているように思いますが、ある程度の規模のソフトを開発するような場合の定石のようなものを示しておきます。
# ソースファイル数が数百以上になるような規模のプロジェクトでは、
# 普通にやっていることだとは思いますが。。。
機能分割やモジュール分割するときに、内部公開用ヘッダと外部公開用ヘッダを用意する場合があります。
こうすることで、機能部外に必要以上の情報を公開する必要もなくなり、No3 buihyaku さんのおっしゃるようなことを極力避けることができるようになります。
たとえば、こんな感じ。
【HOGE 機能部】
〔HOGE_A モジュール〕
(外部公開用ヘッダ) hoge_a.h
(内部公開用ヘッダ) hoge_a_i.h
〔HOGE_B モジュール〕
(外部公開用ヘッダ) hoge_b.h
(内部公開用ヘッダ) hoge_b_i.h
【PIYO 機能部】
〔PIYO_Z モジュール〕
(外部公開用ヘッダ) piyo_z.h
(内部公開用ヘッダ) piyo_z_i.h
で、こんな感じでヘッダファイルをインクルードさせます。
========================================================
[hoge_a.c]
--------------------------------------------------------
#include "hoge_a_i.h"
#include "hoge_b_i.h"
#include "piyo_z.h"
========================================================
[hoge_b.c]
--------------------------------------------------------
#include "hoge_a_i.h"
#include "hoge_b_i.h"
#include "piyo_z.h"
========================================================
[piyo_z.c]
--------------------------------------------------------
#include "hoge_a.h"
#include "hoge_b.h"
#include "piyo_z_i.h"
========================================================
また、この場合、こんな感じで内部公開ヘッダに外部公開ヘッダをインクルードしておきます。
========================================================
[hoge_a_i.h]
--------------------------------------------------------
#include "hoge_a.h"
========================================================
[hoge_b_i.h]
--------------------------------------------------------
#include "hoge_b.h"
========================================================
[piyo_z_i.h]
--------------------------------------------------------
#include "piyo_z.h"
========================================================
さて、上記のヘッダファイルの構築法ですが、下記のように考えればよいのではないでしょか。
(1) 最初は 1ファイルの小さなソースファイルでプログラムを作成。
この場合、ヘッダファイルを作成する必要はありません。
(2) 機能拡張していくと、1ファイルではメンテナンスしきれないくらいコードが肥大化してくるため、機能ごとに別ファイルにする (機能分割)。
この場合、機能ごとにヘッダファイルが必要になる。
(3) さらに機能部に対して機能拡張していくと、やはりコードの肥大化によりメンテナンスが困難になってくるため、機能部をモジュールごとに別ファイルにする (モジュール分割)。
この場合、必要に応じてモジュールごとのヘッダファイルを用意する。
また、(2) で作成したヘッダファイルのうち、分割したモジュールに関連する部分を「外部公開ヘッダ」、モジュール分割により新たに必要になったヘッダファイルを「内部公開ヘッダ」として作成する。
とりあえず、ご参考まで。
長々と失礼しました。
No.6
- 回答日時:
まともな回答は既にされているので、
邪道な解答を書きます。
ヘッダーファイルの話でないので質問の趣旨から外れるかもしれませんが。
状況
10本のプログラムがあり、main関数はほとんど同じ。
それらのmain関数は頻繁に変更され、変更内容は同じ。
このとき、main.cppでそのほとんど同じ内容を書き、各プログラムではそれをincludeするようにした。
異なる部分は#if definedを使って切り分けたが、
その部分もごくわずか。
このようにして、main.pp1本の修正だけで済むようになった。
p.s. 根本的な問題(似たようなプログラムをたくさん作るのがまずい)はおいときます。だって、私が作ったんじゃないですもの。
No.7
- 回答日時:
プロトタイプ宣言の例です。
まず、xxx.cというファイルが一つだけの場合です。xxx.c内の関数fnc1()から同じくxxx.c内のfnc2()を呼び出すとき、fnc2()のほうが後ろに定義されてたら、fnc1()よりも前にfnc2()のプロトタイプ宣言を書きますよね。
次に、yyy.cというファイルがもう一つあって、その中のfnc3()からxxx.cのfnc2()を呼び出すとき、fnc3()の前にfnc2()のプロトタイプ宣言を書けばコンパイルは通りますが、本末転倒です。プロトタイプ宣言はコンパイル時の型チェックのために書くのに、yyy.cで好きなように書くと本来のxxx.cでの定義とずれる可能性があるからです。
そこで、fnc2()のプロトタイプ宣言は定義のあるxxx.cが提供することにして、xxx.hにfnc2()のプロトタイプ宣言を書きます。それを、yyy.cやその他、fnc2()を使いたいファイルがインクルードすれば、コンパイル時に本来の目的のfnc2()の型チェックを行えることになります。
プロトタイプ宣言以外の#defineやstruct定義も同様ではないでしょうか。各ファイル内でそれぞれ同じものを定義してもコンパイルは通りますが、提供元がヘッダとして公開してそれを共有することでファイル間で定義を一意のものとする、という感じではないでしょうか。
逆に言えば、他のファイルに公開したくないstructなどは.cファイルのほうに記述することで、隠蔽できます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# メインプログラムに#include <algorithm>を書いて、 そのメインプログラムが // 3 2023/05/02 11:24
- C言語・C++・C# visual studio 2019を使っているのですが、何か間違ったところをクリックしてしまい画像 2 2023/03/06 06:46
- C言語・C++・C# VisualStudioでC++クラスを追加するとき、ファイルを所定のフォルダ下につくりたい 3 2023/08/24 17:17
- その他(ソフトウェア) Googleフォーム、効率的な入れ方 2 2022/10/03 22:44
- その他(プログラミング・Web制作) プログラムの勉強のおすすめは 7 2022/12/09 20:09
- 教育・学術・研究 著作権法 3 2022/09/15 16:28
- 図書館情報学 著作権の考え方 2 2022/09/15 16:26
- 図書館情報学 著作権 3 2022/10/10 21:43
- 財務・会計・経理 業者間での注文書・請書の取り扱いについて 2 2022/06/27 15:53
- 図書館情報学 著作権について(再質問で申し訳ありません) 1 2022/09/16 23:32
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語初心者の質問失礼します。
-
バッチで118項目のCSVを処理し...
-
csvファイルを開かずに文字を検...
-
iniファイルに追記がしたいです。
-
SGファイルって何ですか?
-
ファイル名の先頭にアンダース...
-
ドラッグアンドドロップでファ...
-
大きいサイズのテキストファイ...
-
テキストファイルの最終行を削...
-
同じ名前のファイルを作った場...
-
C言語関数違いについて。
-
Excelマクロでの再読込み方法
-
WAVファイル同士の結合が可...
-
複数ブックの統合について Exce...
-
Cでのネットワークファイルの読...
-
fopenの"r+"モードで同時に読み...
-
C言語のfopenについて教えてく...
-
文書から任意の文字を抽出する...
-
HTMLファイルをメモ帳から開きたい
-
CSVファイル読み込み
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語初心者の質問失礼します。
-
csvファイルを開かずに文字を検...
-
ファイル名の先頭にアンダース...
-
CSVファイルへの保存の際、デー...
-
ファイルを記録してあるセクタ...
-
テキストファイルの最終行を削...
-
SGファイルって何ですか?
-
ドラッグアンドドロップでファ...
-
分割コンパイルの#defineについて
-
VBに、Cのincludeのようなもの...
-
fopenできる上限の変更
-
グローバル変数のよくない使い...
-
ファイルの結合
-
大きいサイズのテキストファイ...
-
iniファイルに追記がしたいです。
-
バッチで118項目のCSVを処理し...
-
ハッシュの計算時間について
-
C言語のfopenについて教えてく...
-
Javascript で INI の読み書き
-
Excelマクロでの再読込み方法
おすすめ情報