こちらのサイトでファイルの分割について読みました。
http://9cguide.appspot.com/20-01.html
このサイトの中で、「ソースファイルとヘッダーファイルは、通常、1対1で対応するように作成します。」というのがよくわかりません。
例えばmainファイルでexample.hを読み込んだとし、その中でsum関数が定義されていたとします。そしてexample.cppの中でsum関数の中身を書いたとし、それをmain関数の中で使うとします。
これが問題ないのはわかるのですが、例えばexample.hの中で二つの関数sum関数とsum1関数があったとしてそれをexample.cppの中で二つ書いたとしてそれは通るのでしょうか? あるいは二つの関数をexample.cppとexample2.cppにsumとsum1を分けて書いたとき通るのか?(つまりこの場合はヘッダファイルとソースファイルは一対一に対応していません)
質問の仕方を変えると、コンパイラの中でどのようにヘッダファイルとソースファイルを結びつけているのかということです。多少自分でも試してみたのですが、例えばexample.hの中でsum関数を定義し、それをsum.cppの中で書いても、プログラムは通りました。これはつまり、ファイルの名称で判断しているわけではないということだと思うのです。
このあたりがいまいちピンときません。何とぞよろしくお願いします。
ファイルの分割について質問
Re:ファイルの分割について質問
おっしゃってる意味が今ひとつ分かりません。
リンク先のサイトは見てませんが、ソースファイルとヘッダファイルが1対1で対応するというのは、
hoge.cpp で実装を行い、hoge.h では hoge.cpp を使うための宣言やらなんやらを書きましょう。 ということだと思いますよ。
こうしておくことで、hoge.cpp の機能を使いたい場合は、対応している hoge.h を include することで利用可能となります。
基本的にソースファイルは見られてはいけない部分で、ヘッダファイルは公開する部分だと思っていてください。
>例えばmainファイルでexample.hを読み込んだとし、その中でsum関数が定義されていたとします。そしてexample.cppの中でsum関数の中身を書いたとし、それをmain関数の中で使うとします。
言いたいことは解ります。 重隅のようですが一応念のため。
この場合、example.h で関数のプロトタイプ宣言を行い、example.cpp で定義するのが一般的です。
>質問の仕方を変えると、コンパイラの中でどのようにヘッダファイルとソースファイルを結びつけているのかということです。
結びつける。 というのがよく分かりませんが、ヘッダファイルを include することでソースファイルからヘッダファイルを見ることが出来ます。
乱暴な言い方になりますが、#include ディレクティブは、指定したファイルをその場に貼り付けるものだと思っていてとりあえず問題はありません。
ということを聞きたいのでしょうか。 ちょっと自信がありません。
リンク先のサイトは見てませんが、ソースファイルとヘッダファイルが1対1で対応するというのは、
hoge.cpp で実装を行い、hoge.h では hoge.cpp を使うための宣言やらなんやらを書きましょう。 ということだと思いますよ。
こうしておくことで、hoge.cpp の機能を使いたい場合は、対応している hoge.h を include することで利用可能となります。
基本的にソースファイルは見られてはいけない部分で、ヘッダファイルは公開する部分だと思っていてください。
>例えばmainファイルでexample.hを読み込んだとし、その中でsum関数が定義されていたとします。そしてexample.cppの中でsum関数の中身を書いたとし、それをmain関数の中で使うとします。
言いたいことは解ります。 重隅のようですが一応念のため。
この場合、example.h で関数のプロトタイプ宣言を行い、example.cpp で定義するのが一般的です。
>質問の仕方を変えると、コンパイラの中でどのようにヘッダファイルとソースファイルを結びつけているのかということです。
結びつける。 というのがよく分かりませんが、ヘッダファイルを include することでソースファイルからヘッダファイルを見ることが出来ます。
乱暴な言い方になりますが、#include ディレクティブは、指定したファイルをその場に貼り付けるものだと思っていてとりあえず問題はありません。
ということを聞きたいのでしょうか。 ちょっと自信がありません。
Re:ファイルの分割について質問
コンパイラの中では渡されるソースファイルからコンパイルを行います。
この時コンパイラは、コンパイルするファイルを知るために指定したファイルを読み込む(インクルードする)だけで、
コンパイラにはファイル名からそのファイルの役割を決めることはありません。
(ヘッダファイル読み込みモードといったようなものは一切ありません)
つまり、main.cpp をコンパイルするときに main.h を読み込んでも、 example.h を読み込んでも、
はたまた example.cpp を読み込んでも、すべてコンパイラは同一に読み込み、コンパイルを行います。
#inlucde は、指定したファイルの中身が、あたかもそこ(#include 文が書かれている場所)に書かれているかのようにコンパイラはふるまいます。
そのため、ソースファイルとヘッダーファイルは1対1で対応しなくとも中身が正しければ問題なく通ります。
一つのヘッダーファイルにたくさんの関数の宣言などを記述し、個々の定義をたくさんのソースファイルに書いても問題ありません。
「1対1で対応するように」と書いているのは、人から見て一番わかりやすいファイル構成だからです。
sound.h と sound.cpp があれば、サウンドを扱う関数宣言しているヘッダーファイルとそれを定義しているソールファイルだとすぐにわかります。
この時コンパイラは、コンパイルするファイルを知るために指定したファイルを読み込む(インクルードする)だけで、
コンパイラにはファイル名からそのファイルの役割を決めることはありません。
(ヘッダファイル読み込みモードといったようなものは一切ありません)
つまり、main.cpp をコンパイルするときに main.h を読み込んでも、 example.h を読み込んでも、
はたまた example.cpp を読み込んでも、すべてコンパイラは同一に読み込み、コンパイルを行います。
#inlucde は、指定したファイルの中身が、あたかもそこ(#include 文が書かれている場所)に書かれているかのようにコンパイラはふるまいます。
そのため、ソースファイルとヘッダーファイルは1対1で対応しなくとも中身が正しければ問題なく通ります。
一つのヘッダーファイルにたくさんの関数の宣言などを記述し、個々の定義をたくさんのソースファイルに書いても問題ありません。
「1対1で対応するように」と書いているのは、人から見て一番わかりやすいファイル構成だからです。
sound.h と sound.cpp があれば、サウンドを扱う関数宣言しているヘッダーファイルとそれを定義しているソールファイルだとすぐにわかります。
Re:ファイルの分割について質問
極論を言えばヘッダファイルはコンパイル時に参照する情報なので、各cppファイル側に同じことを書くのであれば必要ありません。同じこと書く&メンテナンスが面倒なのでヘッダにまとめているだけです。
で、各cppファイルはヘッダファイルの内容を組み込んだ上でコンパイルされてオブジェクトファイルに変換されます。これは、各cppファイル間の参照に付いては解決していない機械語が格納されたファイルです。
このファイルをリンカで各ファイル間の参照を解決してexeファイルにします。
つまり各ファイル間の参照を解決するのはリンカです。
リンカはヘッダファイルを参照することはありません。
で、各cppファイルはヘッダファイルの内容を組み込んだ上でコンパイルされてオブジェクトファイルに変換されます。これは、各cppファイル間の参照に付いては解決していない機械語が格納されたファイルです。
このファイルをリンカで各ファイル間の参照を解決してexeファイルにします。
つまり各ファイル間の参照を解決するのはリンカです。
リンカはヘッダファイルを参照することはありません。
Re:ファイルの分割について質問
……なかなか難しいですね。皆様のおっしゃってるところが理解できる部分とそうでない部分があります。
ただ御津凪様のおっしゃった
>>#inlucde は、指定したファイルの中身が、あたかもそこ(#include 文が書かれている場所)に書かれているかのようにコンパイラはふるまいます。
>>そのため、ソースファイルとヘッダーファイルは1対1で対応しなくとも中身が正しければ問題なく通ります。一つのヘッダーファイルにたくさんの関数の宣言などを記述し、個々の定義をたくさんのソースファイルに書いても問題ありません。
で、なんとなく答えは出た気がします。
ただ、まだ理解不足の点が多いので、皆様のキーワードを参考にいろいろ勉強してみようと思います。へろり様、御津凪様、softya様、お忙しいところいろいろとご教授いただき、どうもありがとうございました。
ただ御津凪様のおっしゃった
>>#inlucde は、指定したファイルの中身が、あたかもそこ(#include 文が書かれている場所)に書かれているかのようにコンパイラはふるまいます。
>>そのため、ソースファイルとヘッダーファイルは1対1で対応しなくとも中身が正しければ問題なく通ります。一つのヘッダーファイルにたくさんの関数の宣言などを記述し、個々の定義をたくさんのソースファイルに書いても問題ありません。
で、なんとなく答えは出た気がします。
ただ、まだ理解不足の点が多いので、皆様のキーワードを参考にいろいろ勉強してみようと思います。へろり様、御津凪様、softya様、お忙しいところいろいろとご教授いただき、どうもありがとうございました。