引数の一致
オーバーロード関数は、関数呼び出しで指定された引数に最も合った現在のスコープ内の関数宣言に対して選択します。 適切な関数がある場合、その関数が呼び出されます。 "適切" とは、このコンテキストでは次のいずれかを意味します。
厳密な一致が見つかりませんでした。
単純変換が実行されました。
整数の上位変換が実行されました。
目的の引数の型への標準変換が存在します。
目的の引数の型へのユーザー定義の変換 (変換演算子またはコンストラクター) が存在します。
省略記号によって表される引数が見つかりませんでした。
コンパイラは、引数ごとに候補関数のセットを作成します。 候補関数は、その位置の実引数を仮引数の型に変換できる関数です。
一連の "最も一致する関数" は各引数にビルドされ、選択した関数はすべての設定の交差部分です。 交差部分に複数の関数が含まれている場合、オーバーロードはあいまいで、エラーが生成されます。 最終的に選択された関数は、少なくとも 1 つの引数についてはグループ内のどの関数よりも優れた一致です。 このようにならない場合 (明確な勝者が存在しない場合)、関数呼び出しでエラーが生成されます。
次の宣言を考えます (関数には、以下の説明での識別のために Variant 1、Variant 2、および Variant 3 とマーク付けしています)。
Fraction &Add( Fraction &f, long l ); // Variant 1
Fraction &Add( long l, Fraction &f ); // Variant 2
Fraction &Add( Fraction &f, Fraction &f ); // Variant 3
Fraction F1, F2;
次のステートメントを考えます。
F1 = Add( F2, 23 );
前のステートメントは 2 つのセットをビルドします。
セット 1: Fraction 型の第 1 引数を持つ候補関数 |
セット 2: 第 2 引数を int 型に変換できる候補関数 |
---|---|
バリアント 1 |
バリアント 1 (int は、標準変換を使用して long に変換することができます) |
バリアント 3 |
|
セット 2 の関数は、実際のパラメーターの型から仮パラメーターの型に暗黙的に変換される関数です。このような関数の中には、実際のパラメーターの型を仮パラメーターの型に変換する "コスト" が最も小さい関数が 1 つあります。
これら 2 つのセットの積集合は、バリアント 1 です。 あいまいな関数呼び出しの例は次のとおりです。
F1 = Add( 3, 6 );
前の関数呼び出しは次のセットをビルドします。
セット 1: int 型の第 1 引数を持つ候補関数 |
セット 2: int 型の第 2 引数を持つ候補関数 |
---|---|
バリアント 2 (int は、標準変換を使用して long に変換することができます) |
バリアント 1 (int は、標準変換を使用して long に変換することができます) |
この 2 つのセット間の積集合が空であることに注意してください。 このため、エラー メッセージが生成されます。
引数の一致においては、n 個の既定の引数を持つ関数は、それぞれ異なる数の引数を持つ n+1 個の個別の関数として扱われます。
省略記号 (...) はワイルドカードとして機能します。これは任意の実際の引数と一致します。 オーバーロード関数セットを非常に注意して設計しないと、これが多くのあいまいさの原因になる可能性があります。
注意
オーバーロードされた関数のあいまいさは、関数呼び出しが出現するまで判断できません。その時点で、設定は関数呼び出しの引数ごとに構築され、明確なオーバーロードがあるかどうかを確認できます。これは、それらが特定の関数呼び出しによって呼び出されるまで、コードにあいまいさが残ることを意味しています。