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)
{
}
どちらも機能します。これは標準的な方法で、その理由は何ですか?
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)
{
}
どちらも機能します。これは標準的な方法で、その理由は何ですか?
宣言をヘッダー ファイルに配置し、定義を別の.cpp
ファイルに配置し#include
、ヘッダーを別の.cpp
ファイルに配置すると、違いがわかります。
具体的には、次のように仮定します。
int Add(int a, int b);
int Add(int a, int b = 3) {
...
}
#include "lib.h"
int main() {
Add(4);
}
のコンパイルはtest.cpp
デフォルトのパラメーター宣言を認識せず、エラーで失敗します。
このため、デフォルトのパラメーター定義は通常、関数宣言で指定されます。
int Add(int a, int b = 3);
C++ では、パラメーター リスト内の位置に関して既定の引数に課せられる要件は次のとおりです。
特定のパラメーターのデフォルト引数は、1 回しか指定する必要がありません。複数回指定することは (同じデフォルト値であっても) 不正です。
デフォルトの引数を持つパラメータは、パラメータ リストの最後に連続したグループを形成する必要があります。
ここで、C++ では、上記の要件が継続的に満たされている限り、関数の 1 つの宣言から次の宣言まで、既定の引数を持つパラメーターのセットを「成長」させることができます。
たとえば、デフォルト引数のない関数を宣言できます
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 番目のパラメーターに 1 つ追加します。
両方の宣言の正味の効果 (つまり、2 番目の宣言に続くコードから見た場合) はまったく同じです。関数には、2 番目のパラメーターのデフォルト引数があります。ただし、最初の宣言と 2 番目の宣言の間に何らかのコードを詰め込むことができた場合、これら 2 つのバリアントは異なる動作をします。2 番目のバリアントでは、関数には宣言間にデフォルトの引数がないため、両方の引数を明示的に指定する必要があります。
最初の方法は、2 番目の方法よりも優先されます。
これは、パラメーターがオプションであり、そのデフォルト値がどうなるかがヘッダー ファイルに示されるためです。さらに、これにより、対応する .cpp ファイルの実装に関係なく、デフォルト値が同じになることが保証されます。
2 番目の方法では、2 番目のパラメーターのデフォルト値は保証されません。対応する .cpp ファイルがどのように実装されているかによって、デフォルト値が変わる可能性があります。
既定の引数は、関数名が最初に出現する場所 (通常は関数プロトタイプ内) で指定する必要があります。関数定義がプロトタイプを兼ねているために関数プロトタイプを省略する場合は、デフォルトの引数を関数ヘッダーに指定する必要があります。