C++ 関数

関数は、一緒にタスクを実行する文の集まりです。すべての C++ プログラムには少なくとも 1 つの関数、つまりメイン関数がありますmain()、すべての単純なプログラムは、他の追加の関数も定義できます。

コードをさまざまな関数に分割できます。コードをどのように関数に分割するかはあなた次第ですが、論理的には、通常は各関数が特定のタスクを実行するように分割します。

関数宣言コンパイラに関数の名前、戻り値の型、パラメータを伝えます。関数定義は関数の実際の本体を提供します。

C++ 標準ライブラリには、プログラムが呼び出せる多数の組み込み関数があります。たとえば、関数strcat()は2つの文字列を連結するために使われ、関数memcpy()はメモリを別の場所にコピーするために使われます。

関数には、メソッド、サブルーチン、プロシージャなど、さまざまな呼び方もあります。

関数の定義

C++ における関数定義の一般的な形式は次のとおりです:

return_type function_name( parameter list ) { body of the function }

C++ では、関数は関数ヘッダと関数本体で構成されます。以下に関数のすべての構成要素を示します:

  • 戻り値の型:関数は値を1つ返すことができます。return_typeは関数が返す値のデータ型です。一部の関数は必要な操作を実行しても値を返しません。この場合、return_type はキーワードvoid。
  • 関数名:これは関数の実際の名前です。関数名とパラメータリストは一緒になって関数シグネチャを構成します。
  • パラメータ:パラメータはプレースホルダのようなものです。関数が呼び出されるとき、パラメータに値を渡します。この値を実引数と呼びます。パラメータリストには、関数パラメータの型、順序、数が含まれます。パラメータは省略可能であり、つまり関数はパラメータを含まない場合もあります。
  • 関数本体:関数本体には、関数が実行するタスクを定義する一連の文が含まれます。

例

以下はmax()関数のソースコードです。この関数には num1 と num2 の2つのパラメータがあり、これら2つの数値のうち大きい方を返します:

// 2つの数値のうち大きい方を返す関数 int max(int num1, int num2) { // ローカル変数の宣言 int result; if (num1 > num2) result = num1; else result = num2; return result; }

関数の宣言

関数宣言はコンパイラに関数名と関数の呼び出し方を伝えます。関数の実際の本体は個別に定義できます。

関数の宣言には次の部分が含まれます:

return_type function_name( parameter list );

上で定義した関数 max() について、以下が関数の宣言です:

int max(int num1, int num2);

関数の宣言では、パラメータ名は重要ではなく、パラメータの型のみが必要です。したがって、次も有効な宣言です:

int max(int, int);

あるソースファイルで関数を定義し、別のファイルでその関数を呼び出す場合、関数の宣言が必要です。この場合、関数を呼び出すファイルの先頭で関数を宣言する必要があります。

関数の呼び出し

C++ 関数を作成するとき、関数が何を行うかを定義し、それから関数を呼び出して定義したタスクを実行します。

プログラムが関数を呼び出すと、プログラムの制御は呼び出された関数に移ります。呼び出された関数は定義されたタスクを実行し、関数の return 文が実行されるか、関数の終了中括弧に達すると、プログラムの制御はメインプログラムに戻されます。

関数を呼び出すとき、必要なパラメータを渡します。関数が値を返す場合は、戻り値を保存できます。例:

例

#include <iostream> using namespace std; // 関数の宣言 int max(int num1, int num2); int main () { // ローカル変数の宣言 int a = 100; int b = 200; int ret; // 関数を呼び出して最大値を取得する ret = max(a, b); cout << "Max value is : " << ret << endl; return 0; } // 2つの数値のうち大きい方を返す関数 int max(int num1, int num2) { // ローカル変数の宣言 int result; if (num1 > num2) result = num1; else result = num2; return result; }

max() 関数と main() 関数を一緒に置いて、ソースコードをコンパイルします。最終的な実行可能ファイルを実行すると、次の結果が生成されます:

Max value is : 200

関数のパラメータ

関数がパラメータを使用する場合、パラメータ値を受け取る変数を宣言する必要があります。これらの変数は関数の仮引数。

仮引数は関数内の他のローカル変数と同様に、関数に入るときに作成され、関数を出るときに破棄されます。

関数を呼び出すとき、関数にパラメータを渡す方法は3つあります:

呼び出しの種類説明
値渡しこの方法では、パラメータの実際の値を関数の仮引数に代入します。この場合、関数内で仮引数を変更しても実引数には影響しません。
ポインタ渡しこの方法では、パラメータのアドレスを仮引数に代入します。関数内では、そのアドレスを使用して呼び出しで使用される実引数にアクセスします。つまり、仮引数を変更すると実引数に影響します。
参照渡しこの方法では、パラメータの参照を仮引数に代入します。関数内では、その参照を使用して呼び出しで使用される実引数にアクセスします。つまり、仮引数を変更すると実引数に影響します。

デフォルトでは、C++ は値渡しを使用してパラメータを渡します。一般に、これは関数内のコードが関数の呼び出しに使用された引数を変更できないことを意味します。前述の例では、max() 関数を呼び出すときに同じ方法が使用されました。

パラメータのデフォルト値

関数を定義するとき、パラメータリストの後ろにある各パラメータにデフォルト値を指定できます。関数を呼び出すときに、実引数の値を空のままにすると、このデフォルト値が使用されます。

これは、関数定義で代入演算子を使用してパラメータに値を割り当てることによって行われます。関数を呼び出すとき、パラメータの値が渡されない場合はデフォルト値が使用され、値が指定された場合はデフォルト値は無視されて渡された値が使用されます。次の例を参照してください:

例

#include <iostream> using namespace std; int sum(int a, int b=20) { int result; result = a + b; return (result); } int main () { // ローカル変数の宣言 int a = 100; int b = 200; int result; // 関数を呼び出して値を追加する result = sum(a, b); cout << "Total value is :" << result << endl; // 関数を再度呼び出す result = sum(a); cout << "Total value is :" << result << endl; return 0; }

上記のコードをコンパイルして実行すると、次の結果が生成されます:

Total value is :300
Total value is :120

Lambda 関数と式

C++11 は匿名関数のサポートを提供します。これは Lambda 関数(Lambda 式とも呼ばれます)と呼ばれます。

Lambda 式は関数をオブジェクトとして扱います。Lambda 式はオブジェクトのように使用でき、変数に代入したりパラメータとして渡したり、関数のように評価したりできます。

Lambda 式は本質的に関数宣言と非常によく似ています。Lambda 式の具体的な形式は次のとおりです:

[capture](parameters)->return-type{body}

例:

[](int x, int y){ return x < y ; }

戻り値がない場合は次のように表すことができます:

[capture](parameters){body}

例:

[]{ ++global_x; } 

より複雑な例では、戻り値の型を次のように明示的に指定できます:

[](int x, int y) -> int { int z = x + y; return z + x; }

この例では、中間結果を格納するために一時的なパラメータ z が作成されます。通常の関数と同様に、z の値は、次にこの匿名関数が再び呼び出されたときに保持されることはありません。

lambda 関数が値を返さない場合(void など)、その戻り値の型は完全に無視できます。

Lambda 式内では現在のスコープの変数にアクセスできます。これは Lambda 式のクロージャ(Closure)動作です。JavaScript のクロージャとは異なり、C++ の変数渡しには値渡しと参照渡しの違いがあります。先頭の [] で指定できます:

[]      // 沒有定义任何变量。使用未定义变量会引发错误。
[x, &y] // x以传值方式传入(默认),y以引用方式传入。
[&]     // 任何被使用到的外部变量都隐式地以引用方式加以引用。
[=]     // 任何被使用到的外部变量都隐式地以传值方式加以引用。
[&, x]  // x显式地以传值方式加以引用。其余变量以引用方式加以引用。
[=, &z] // z显式地以引用方式加以引用。其余变量以传值方式加以引用。

もう1点注意が必要です。[=] または [&] 形式では、lambda 式は this ポインタを直接使用できます。ただし、[] の形式では、this ポインタを使用する場合は明示的に渡す必要があります:

[this]() { this->someFunc(); }();
その他の拡張