C++によるソフトウェア開発の方法いろいろ
目次
main関数にコードを全て記述する
簡単な例として、以下のコードをmain1.cxxに記述する。
#include <iostream> int main(int argc, char* argv[]) { int a=1; int b=2; int c=a+b; std::cout << "Executing main1.exe" << std::endl; std::cout << "a=" << a << " b=" << b << " c=" << c << std::endl; return 0; }
このファイルをコンパイルするには次のコマンドを実行する。
g++ main1.cxx -o main1.exe
これで、main1.exeという実行可能プログラムができて、シェルからコマンドのように呼び出すことで実行できる。
main関数といくつかの関数からなるプログラム(一つのファイル)
上の例で計算している部分を関数にすると次のようなプログラムになる。(main2.cxx)
#include <iostream> int calc1(int a, int b); int main(int argc, char* argv[]) { int a=1; int b=2; int c=calc1(a, b); std::cout << "Executing main1.exe" << std::endl; std::cout << "a=" << a << " b=" << b << " c=" << c << std::endl; return 0; } int calc1(int a, int b) { return a+b; }
のようになる。
関数の宣言と定義
上のコードでmain関数の上にある
int calc1(int a, int b);
を関数の宣言と呼ぶ。宣言は、関数を使う側にとってその関数を呼び出すのに必要な情報だけが含まれている。具体的には、関数名、必要な引数リスト、出力値の型のみが必要である。上のコードでは関数宣言がmain関数より先に定義されているため、main関数の中で関数を呼び出す段階ではコンパイラは必要な情報を全て持っている。 これに対して、関数の中で行う具体的な処理は、関数定義で行う。main関数から別の関数を呼び出すためには、宣言のみで十分だが実際に実行するためには関数の中で行う処理(定義)も必要なため、これも一緒に記述して初めて実行可能ファイルを生成することができる。
int calc1(int a, int b) { return a+b; }
このプログラムも以下のコマンドでコンパイルして実行可能ファイルを生成できる。
g++ main2.cxx -o main2.exe
プログラムに必要なコードをいくつかのファイルに分ける
上のようにして定義した関数を別のファイルに記述してみる。次のよう表のようにmain関数を記述するファイルに加えて、利用するその他の関数を別のファイルに記述する必要がある。
*ファイル名* |
用途 |
myfunctions.hxx |
calc(...)関数の宣言のみを記述したファイル(ヘッダーファイル) |
myfunctions.cxx |
calc(...)関数の定義を記述したファイル(ソースファイル) |
main3.cxx |
main関数の定義とcalc(...)関数の呼び出し。 |
この場合、あるコードから別のファイルで定義された関数を呼び出す場合には、その関数の宣言を知る必要がある。宣言のみをまとめたファイルをヘッダーファイルと呼び、このファイルを呼び出す側のファイルからインクルード(include)することが可能である。これは、通常ファイルの先頭で
#include "myfunctions.hxx"
のように、#include文を使って行う。この一行は指定したファイルの中身をそこに貼り付けたのと同じ効果を持つ。したがって、関数を呼び出す前にその関数の宣言を取り入れることが可能である。
インクルード・ガード
あるソースファイルをコンパイルする際に、いくつかのヘッダーファイルをインクルードした場合、ヘッダーファイルで別のヘッダーファイルをインクルードしていたせいで、同じヘッダーファイルを繰り返しインクルードしてしまう事態が生じうる。そうすると、同じ宣言文が2回現れてしまいコンパイル・エラーが発生してしまう。これを避けるために、通常ヘッダーファイルの中身全体を次のようなマクロ条件文で覆ってしまう。
#ifndef __include_guard_for_file_XXXXX___ #define __include_guard_for_file_XXXXX___ ..... ヘッダーファイルの中身 ..... #ifndef
"include_guard_for_file_XXXXX_"の部分はそのファイルに固有の文字列である必要がある。他の人が簡単にまねしないようなできるだけ複雑な文字列にするのが良い。
複数のライブラリを使ってプログラムを構成する
プログラムがより大規模になると、機能ごとに分けて管理した方が効率的に開発を行える。
プログラムを構成する機能の一部をライブラリにまとめる
複数のライブラリと1つのmain関数から実行可能プログラムを作る
大量のライブラリを利用する場合
リンクすらしない方法。 Athena, web service, ...