web-dev-qa-db-ja.com

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

1。

int Add (int a, int b = 3);
int Add (int a, int b)
{

}

2。

int Add (int a, int b);
int Add (int a, int b = 3)
{

}

両方とも機能します。これは標準的な方法であり、なぜ

122
httpinterpret

宣言をヘッダーファイルに配置し、定義を別の.cppファイルに配置し、#includeヘッダーを別の.cppファイルから配置すると、違いを確認できます。

具体的には、次のことを想定します。

lib.h

int Add(int a, int b);

lib.cpp

int Add(int a, int b = 3) {
   ...
}

test.cpp

#include "lib.h"

int main() {
    Add(4);
}

test.cppのコンパイルではデフォルトのパラメーター宣言は表示されず、エラーで失敗します。

このため、デフォルトのパラメーター定義は通常、関数宣言で指定されます。

lib.h

int Add(int a, int b = 3);
190
Greg Hewgill

C++では、パラメータリスト内の位置に関してデフォルト引数に課される要件は次のとおりです。

  1. 特定のパラメーターのデフォルト引数は、1回しか指定する必要はありません。 (デフォルト値が同じであっても)複数回指定することは違法です。

  2. デフォルト引数を持つパラメーターは、パラメーターリストの最後に連続したグループを形成する必要があります。

さて、それを念頭に置いて、C++では、上記の要件が継続的に満たされる限り、関数の宣言から次の宣言にデフォルト引数を持つパラメーターのセットを「成長」させることができます。

たとえば、デフォルト引数なしで関数を宣言できます

void foo(int a, int b);

そのような宣言の後にその関数を呼び出すには、両方の引数を明示的に指定する必要があります。

後で(さらに下に)同じ翻訳単位で再度宣言できますが、今回は1つのデフォルト引数を使用します。

void foo(int a, int b = 5);

この時点から、1つの明示的な引数だけで呼び出すことができます。

さらに下に再度宣言して、もう1つのデフォルト引数を追加できます。

void foo(int a = 1, int b);

この時点から、明示的な引数なしで呼び出すことができます。

完全な例は次のようになります

void foo(int a, int b);

int main()
{
  foo(2, 3);

  void foo(int a, int b = 5); // redeclare
  foo(8); // OK, calls `foo(8, 5)`

  void foo(int a = 1, int b); // redeclare again
  foo(); // OK, calls `foo(1, 5)`
}

void foo(int a, int b)
{
  // ...
}

あなたの質問のコードに関しては、両方のバリアントは完全に有効ですが、それらは異なることを意味します。最初のバリアントは、2番目のパラメーターのデフォルト引数をすぐに宣言します。 2番目のバリアントは、最初にデフォルトの引数なしで関数を宣言し、2番目のパラメーターに関数を追加します。

両方の宣言の正味の効果(つまり、2番目の宣言に続くコードで見られる方法)はまったく同じです:関数は2番目のパラメーターにデフォルト引数を持っています。ただし、最初の宣言と2番目の宣言の間でコードを圧縮する場合、これら2つのバリアントの動作は異なります。 2番目のバリアントでは、関数は宣言間にデフォルト引数を持たないため、両方の引数を明示的に指定する必要があります。

43
AnT

最初の方法が2番目の方法よりも優先されます。

これは、ヘッダーファイルに、パラメーターがオプションであり、そのデフォルト値が何であるかが表示されるためです。さらに、これにより、対応する.cppファイルの実装に関係なく、デフォルト値が同じになることが保証されます。

2番目の方法では、2番目のパラメーターのデフォルト値の保証はありません。デフォルト値は、対応する.cppファイルの実装方法に応じて変わる可能性があります。

5
user342264

デフォルト引数は、関数名が最初に現れるときに指定する必要があります。通常は、関数プロトタイプで指定します。関数定義がプロトタイプとしても機能するために関数プロトタイプが省略されている場合は、デフォルトの引数を関数ヘッダーで指定する必要があります。

4
clyfe