多重定義された関数のアドレスの解決 (C++ のみ)

引数が指定されていない多重定義された関数名 f を使用する場合、 その名前は、関数、関数を指すポインター、メンバー関数を指すポインター、 または関数テンプレートの特殊化を参照することができます。 引数が指定されなかったので、コンパイラーは、 関数呼び出しまたは演算子の使用に対して実行するのと同じ方法では、 多重定義解決を実行することができません。 その代わりに、コンパイラーは、f を使用した場所に応じて、 以下の式のうちの 1 つの式の型に一致する、最良の実行可能関数を選択しようと試みます。
  • 初期化しようとしているオブジェクトまたは参照
  • 代入の左辺
  • 関数またはユーザー定義の演算子のパラメーター
  • 関数、演算子、または変換の戻り値
  • 明示的型変換
ユーザーが f を使用したときに、 コンパイラーが非メンバー関数または静的メンバー関数を選択した場合、コンパイラーは、 宣言を型「ポインターから関数へ」または「参照から関数へ」の式に突き合わせました。 コンパイラーが非静的メンバー関数の宣言を選択した場合、コンパイラーは、 その宣言を型「ポインターからメンバー関数へ」の式に突き合わせました。 次の例は、このことを示しています。
struct X {
  int f(int) { return 0; }
  static int f(char) { return 0; }
};

int main() {
  int (X::*a)(int) = &X::f;
//  int (*b)(int) = &X::f;
}
コンパイラーは、関数ポインター b の初期化を許可しません。 型 int(int) の非メンバー関数または静的関数は、宣言されていません。
f がテンプレート関数の場合、コンパイラーは、テンプレート引数推論を実行して、 どのテンプレート関数を使用するかを決めます。 うまくいけば、その関数を実行可能関数のリストに追加します。 このセットに、非テンプレート関数を含めて、複数の関数がある場合、 コンパイラーは、セットからすべてのテンプレート関数を除去し、非テンプレート関数を選択します。 このセットにテンプレート関数だけがある場合、 コンパイラーは、最も特殊化されたテンプレート関数を選択します。 次の例は、このことを示しています。
template<class T> int f(T) { return 0; }
template<> int f(int) { return 0; }
int f(int) { return 0; }

int main() {
  int (*a)(int) = f;
  a(1);
}

関数呼び出し a(1) は、int f(int) を呼び出します。