関数の定義は今まで main の前に書いてきました。しかし、main の後ろに書くこともできるのです。今回はそういうことを話していきます。
では、今回の要点です。
では、いってみましょう。
さて、関数は使う前に宣言する必要があります。ですが、関数の量が多くなってくると、関数を並べる順番を考えるのが面倒になってきます。
このようなときは関数のプロトタイプを使うと便利になります。
では、先ず次のプログラムを見て下さい。
プログラム | 実行結果 |
---|---|
// Proto1.cpp #include <iostream.h> int f(int x, int y); int main() { cout << "f(1, 2) = " << f(1, 2) << endl; cout << "f(158, 144) = " << f(158, 144) << endl; return 0; } int f(int x, int y) { return 5 * x - 2 * y; } |
f(1, 2) = 1 f(158, 144) = 502 |
少し f の中身が変わっていますが、関数の説明の時に使ったものとほとんど同じですね。
f の定義はきちんと main の後ろにかかれていますね。ですが、その代わりに何かが上に書かれているようです。
int f(int x, int y);
これが噂の関数のプロトタイプです。
どんな変わったことをするのかと思えば、何でもない。ただ中身が書かれていないだけですね。ただ、引数の名前が書かれていますが、別に書かれていなくても構いません。
で、定義の部分はといえば、ごく普通の関数の定義の書式です。本当に何の変わりもありません。
この方法の利点はいろいろあります。そのうちの1つは次章に話すインクルードというものが関係してきます。
そして、もう1つはさっき話した通り、関数の順番を気にしなくていいということです。
新しい関数を作るときには、普通、使う関数の下に書きたくなるでしょう。ですが、今までの方法ではそれができませんでした。これからは、そういうときは関数のプロトタイプを書いておいてから、そういう順番に並べてやればいいのです。
プログラム |
---|
// Proto2.cpp #include <iostream.h> void func6(){ cout << "ご苦労さん" << endl; } void func5(){ func6(); } void func4(){ func5(); } void func3(){ func4(); } void func2(){ func3(); } void func1(){ func2(); } int main() { func1(); return 0; } |
例えば右のような感じのプログラムを作ることがあったとしましょう。(このまんまのを作ることは、まずないでしょうが。)
このとき、プログラムの流れを読もうとすると、下から読まなくてはいけませんね。これは非常に面倒です。
プログラム |
---|
// Proto2.cpp #include <iostream.h> void func1(); void func2(); void func3(); void func4(); void func5(); void func6(); int main() { func1(); return 0; } void func1(){ func2(); } void func2(){ func3(); } void func3(){ func4(); } void func4(){ func5(); } void func5(){ func6(); } void func6(){ cout << "ご苦労さん" << endl; } |
そこを、右のようにすれば、見やすくなると思います。
打ち込む量は増えますが、見やすく、作りやすくなる上に全関数リストができるので、その有用性は高いと思います。
実際に大きなプログラムを作るときは次章の方法を使うので、この方法を使わざるを得なくなります。今のうちに慣れておくことをおすすめします。
何故これでいいのか気になる人がいるかもしれません。一応説明しますが、今わからなくても別に気にする必要はありません。
何故これでいいかは、ビルドの方法に起因します。
ビルドというのは2つのプロセスから成り立っています。1つはコンパイルで、もう1つはリンクです。
コンパイルというのは、プログラムを実行ファイルの前段階のファイルに変換する作業です。そしてリンクというのは、そのファイルをいくつか集めて1つの実行ファイルを作る作業です。
コンパイルはファイルの先頭から順に見ていき、そして変換します。なので変数や関数は使う前に宣言しておかなければなりません。
しかし、コンパイルの時には実は関数の場所はまだ定まっていません。「こうこうこういう関数がある」ということは決まっていても、その関数を使うにはどこに飛べばいいかは決まっていないのです。つまり、コンパイル時にはどこに飛ぶかがどうせ決まっていないのですから、プロトタイプを書くだけで事足りるのです。
関数の場所が決まり、どこに飛ぶかを設定するのはリンクの仕事です。「実は中身が定義されていなかった」ということがあれば、リンク時にエラーが出るわけです。
重ねて言いますが、今このことがわからなくてもとりあえずプログラムを組むのには支障ありません。そのうちわかるようになるはずですから、焦らないで下さいね。
次章では、ついに #include の秘密が解き明かされます。楽しみにして下さい。
では、今回の要点です。
次回まで、さようなら。
Last update was done on 1999.3.16
この講座の著作権はロベールが保有しています