多重定義解決

C++最も適切な多重定義された関数または演算子を選択するプロセスは、 多重定義解決 と呼ばれています。

f が、多重定義された関数名であると想定します。 多重定義された関数 f() を呼び出す場合、 コンパイラーは候補関数 のセットを作成します。

この関数のセットには、f() を呼び出したポイントからアクセスできる、f という名前のすべての関数が含まれています。 コンパイラーは、多重定義解決を促進するために、f という名前のこれらのアクセス可能な関数の中の 1 つの関数の代替表記を、 候補関数として含めることができます。

候補関数のセットを作成した後、コンパイラーは、実行可能関数 のセットを作成します。 この関数のセットは、候補関数のサブセットです。 各実行可能関数のパラメーター数は、f() を呼び出すのに使用した引き数の数に一致します。

コンパイラーは、実行可能関数のセットから最良の実行可能関数 を選択します。 これは、f() を呼び出すときに C++ ランタイムが使用する関数宣言です。

コンパイラーは、暗黙的変換シーケンス によって、これを行います。 暗黙的変換シーケンスは、関数呼び出しの中の引き数を、 関数宣言の中の対応するパラメーターの型へ変換するのに必要な変換のシーケンスです。 暗黙的変換シーケンスはランク付けされます。いくつかの暗黙的変換シーケンスは、 他のものより良いシーケンスです。 コンパイラーは、そのすべてのパラメーターが、他のすべての実行可能関数よりも良い、 または等しいランク付けの暗黙的変換シーケンスを持つ、1 つの実行可能関数を検出しようと試みます。 コンパイラーが検出する実行可能関数が、最良の実行可能関数です。 コンパイラーは、コンパイラーが複数の最良実行可能関数を検出できたプログラムは、許可しません。

可変長配列が関数仮パラメーターであるとき、 左端の配列次元では、候補関数間で関数を区別しません。 以下で f の 2 番目の定義が許されないのは、void f(int []) がすでに定義済みであるからです。

void f(int a[*]) {}
void f(int a[5]) {} // illegal

ただし、可変長配列内の左端のもの以外の配列次元は、可変長配列が関数仮パラメーターであるとき、 候補関数の区別を行います。 例えば、関数 f の多重定義セットは、以下の関数から成る可能性があります。

void f(int a[][5]) {}
void f(int a[][4]) {}
void f(int a[][g]) {}   // assume g is a global int

しかし、以下をインクルードすることはできません。

void f(int a[][g2]) {} // illegal, assuming g2 is a global int

2 次レベル配列の次元を伴う候補関数があるため、g および g2 は、どの関数 f が呼び出されるべきかという点にあいまいさを作成します。 g および g2 のいずれもコンパイル時に不明です。

明示的キャストを使用することによって、正確な一致をオーバーライドすることができます。 次の例では、f() に対する 2 回目の呼び出しが f(void*) と一致します。

void f(int) { };
void f(void*) { };
 
int main() {
   f(0xaabb);            // matches f(int);
   f((void*) 0xaabb);    // matches f(void*)
}

関連参照

IBM Copyright 2003