c++のファイル分割とプログラム実行方法
IDE環境だとファイル分割して実行するだけでプログラムを実行してくれるみたい。
今回は手動で実行する手順について書きます。
ホームディレクトリにc++のプロジェクトディレクトリを作成
~/c++/source // main関数と関数のファイルを入れるディレクトリ
~/c++/header // headerファイルを入れるディレクトリ
上記のような感じに、c++ディレクトリの中にsourceディレクトリとheaderディレクトリを作成。
別に分けなくても1つのディレクトリに全部入れた方がラクと思うけど、実際の開発環境ではディレクトリを役割で分けるのが普通なので、今回は勉強のためにディレクトリを分けました。
sourceディレクトリに入れるファイル
main関数の部分が書かれているファイル=hello.cpp
具体的な処理を定義している関数が書かれているファイル=calc.cpp
headerディレクトリに入れるファイル
関数のプロトタイプ宣言が書かれているファイル=
calc.hpp
以上でファイル分割は完了です。
ファイルを#includeで読み込むとき、異なるディレクトリのファイルを読み込む場合はファイル名だけでなく、パスも指定する必要があります。
絶対パスだとコンパイルのときに、なぜかエラーがでました。
原因:普段ターミナル使っていて、ホームディレクトリを「~/」と書くのが普通になっているので、パスの指定の時も~/を書いたのが原因でした。
本当のパス名を入れないと認識してくれないみたいです。
ホームディレクトリの本当のパス名は下記コマンドで確認。
$ echo $HOME
相対パスも認識してくれるけど、間違い易いと思うので、絶対パスでいいかなと思います。
ファイルの中身の書き方は簡単だと思ったので、今回は省略します。
ファイルが揃ったので、次の手順に進みます。
各ファイルをコンパイルしオブジェクトファイルを作成する
headerファイル以外のファイルをコンパイルしオブジェクトファイルを作成します。
ここでは、hello.cppとcalc.cppをコンパイルです。
$ g++ -c hello.cpp -o hello.o
$ g++ -c calc.cpp -o calc.o
-cオプションは、リンクせず個別にコンパイル。おそらくだけど、-cを付けないと依存するファイルにリンクしようとしてしまうのかも。あとでまとめてリンクさせたいので、-cを付けて、リンクはさせないと解釈。
-oオプションは、オブジェクトファイルを作成。
以上のコマンドを実行すると、オブジェクトファイルが出来あがります。これらのオブジェクトファイルをリンクします。
$ g++ hello.o calc.o
g++の引数にリンクさせるオブジェクトファイルを渡します。
すると、a.outというアーカイブファイルが生成されます。
あとは、このアーカイブファイルを実行します。
$ ./a.out
すると、実行内容が出力されます。
以上で基本的なファイル分割の方法は分かったけど、ファイル分割の際に二重インクルードを防止しないと関数の二重定義でエラーが発生する可能性があるので、二重インクルードについても理解しておきたいです。
別途、記事を作成しているので、二重インクルードについては、こちらの記事を参照。
もっと長くて複雑なソースコードをファイル分割する
static変数について
・staticを付けると、そのファイルの中でだけ変数が有効になる。
・関数の中でstaticを付けると、関数の中だけで有効なグローバル変数になる。関数の外から変数の値を変更しようとしたりすると、エラーになる。
・staticを付けると、最初の一度だけ実行される。例えば、static int num = 0;のような変数への値の代入。
#include <stdio.h>
void foo();
int main() {
for (int i = 0; i < 3; i++) {
foo();
}
}
void foo() {
static int num = 0; // staticを付けると最初に一回だけ実行される
printf("num=%d\n", num);
num++;
}
// staticを付けない場合、forループのたびにint num = 0;で初期化されるので、ループ三回の出力結果(num)はどれも0と表示される.
// staticを付けると最初の一回だけint num = 0;が実行されるので、forループでnum++;が反映されて出力される。