大まかに言えば、関数は以下に基づいてオーバーロードできます。
この例は、2 番目の基準を満たしているため、コンパイルされます。
int
とint &
は異なるデータ型です。
次の例を検討してください。
void foo(int i);
void foo(int& i);
void foo(int i){}
void foo(int& i){}
int main()
{
return 0;
}
上記のコードは有効なコードであるため、コンパイルされます。関数に渡される関数引数に応じて、コンパイラは関数呼び出しに最適な一致を検出する場合と検出しない場合があります。そのため、関数自体は共存できますが、特定の方法で使用すると、コンパイラにあいまいさが生じる可能性があります。
例: 次のコードでは、リテラルを非 const 参照にバインドすることはできないため、関数呼び出しの唯一の候補は非参照バージョンであり、これはコンパイルして問題なく動作するはずです。
void foo(int i);
void foo(int& i);
void foo(int i){}
void foo(int& i){}
int main()
{
foo(20);
return 0;
}
しかし、
void foo(int i);
void foo(int& i);
void foo(int i){}
void foo(int& i){}
int main()
{
int i = 10;
foo(i);
return 0;
}
上記は、コンパイラが 2 つの関数呼び出し間の最適な一致を検出できないため、コンパイラにあいまいさを引き起こします。