関数は、いろいろなプログラムの機能を実現する単位といえます。CやC++でプログラムを作るということは、関数を書いていく事といえます。
関数のひとつの約束として、使うより前の位置で定義されている必要があるということです。これは基本的に変数の定義と同じです。例えば、
void show()
{
...省略...
}
void foo()
{
show();
}
は、関数fooので関数showが呼び出されていますが、showはfooの前方で定義されているので正しくコンパイルすることが出来ます。しかし、次の例ではうまくいきません。
void foo()
{
show();
}
void show()
{
...省略...
}
これは、関数fooの中で、showを呼び出していますが、この時点ではshowは定義されていないのでエラーになります。これは、コンパイラが、上から下へプログラムを読んでいくことに原因があります。もし、showの定義をfooよりも下に書く必要がある場合は以下のようにします。
void show(); //プロトタイプ(showをこれから定義するという宣言)
void foo()
{
show();
}
void show()
{
...省略...
}
最初のvoid show();はプロトタイプ宣言といいます。これからこういう関数を定義するという意味です。プロトタイプが定義されていると、fooの中でshowが呼ばれたときshowが関数で何処かで定義される予定であることをコンパイラが理解するので、コンパイルを正しく行うことが出来ます。
C,C++では、コンパイラがどの様に動くかを常に意識してプログラムを書く必要があります。コンパイラの動きを正しく把握できていれば複雑なプログラムを自在に書くことが出来ます。プログラムをコンパイルしたときエラーが出たらなぜそのようなエラーが出たのかをよく考えてみてください。
関数にはいろいろな値を戻すことが出来ます。これは、数字に限らず、文字列や、数字や文字列を組み合わせたより複雑な構造も可能です。
簡単な例では
int add(int a, int b)
{
return a + b;
}
double pi()
{
return 3.14159265358979;
}
です。
文字列も戻せます。
char* hello()
{
char* h = "hello";
return h;
}
STLを使うと文字列の足し算もかけます。(このような関数を書く必要はないかもしれませんが。)
std::string add(std::string a, std::string b)
{
return a + b;
}
class Profile
{
public:
int age;
std::string name;
std::string university;
};
Profile getProfile()
{
Profile p;
p.age = 19;
p.name = "taro";
p.university = "SGU";
return p;
}
上の例では、クラスProfileを使うことによって、年齢と名前と大学名を同時に返す関数getProfileを定義しています。