5

次の関数プロトタイプを検討してください。

void Remove(SomeContainer& Vec, const std::size_t Index);

SomeContainer Remove(SomeContainer Vec, const std::size_t Index);

2 番目は、最初の観点から実装されます。つまり、一方が参照渡しで、もう一方が値渡しであることを除いて、すべての点で機能的に同一です。

ただし、値を返さないのは最初の形式だけですが、GCC は次のような場合はあいまいであると述べています。

Remove(SomeContainer, 123);

これに対する回避策はありますか、または各フォームに異なる名前を付ける必要がありますか?

4

4 に答える 4

5

戻り値の型は、関数のオーバーロードの基礎ではありません。
関数のオーバーロードは、次のいずれかの基準でのみ行うことができます。

  1. 引数の数
  2. 引数の種類 &
  3. 引数のシーケンス

戻り値の型は呼び出し元によって無視される可能性があるため、関数のオーバーロードの有効な基準ではありません。

上記のように、値渡しとリファレンスを渡すと、コンパイラにあいまいさが生じます。例:

void doSomething(int i)
{
}

void doSomething(int &i)
{
}

int main()
{
    int val = 10;
    doSomething(val);   //Ambiguous
}

ここで、コンパイラは のどのvalバージョンに渡すかを判断できませんdoSomething()。どのバージョンに対しても有効な関数呼び出しを行うことができるため、コンパイル時に助けを求めて (これは静的リンクであるため)、呼び出しにあいまいなフラグを立てます。

あなたのような場合。関数の名前を変更するか、2 つの関数をオーバーロードする (同じ名前で引数の型が異なる) ポインター引数を渡すことは、選択/設定です。ただし、設定を選択する際に、要件と関数が実行するアクションを考慮することが重要です。個人的には、オーバーロードのためだけにポインタを選択するつもりはありません。引数を再配置するか、別の変数を指すようにする必要がある場合は、ポインター引数を選択するのが理にかなっています。

簡単な方法は、2 つの異なる関数名を使用することです。オーバーヘッドはなく、他の関数呼び出しと同じくらい効率的です。

于 2011-05-02T12:51:08.973 に答える
3

前述のように、戻り型はオーバーロードの対象とは見なされません。ただし、コンパイラプレーン値を考慮し、さまざまな型を参照しますが、通常、どのバージョンを呼び出すかはわかりません。言い換えると、パラメーターが値渡しか参照渡しかだけが異なる2つのオーバーロードされた関数を持つことは、それを呼び出そうとするまでは問題ありません。潜在的なあいまいさはC++のエラーではありません。

例:

void f(int) {
    cout << "value\n";
}

void f(int&) {
    cout << "reference\n";
}

int main() {
    int  val = 42;

    f(val); // Error! Ambiguous.
    f(static_cast<int>(val)); // OK: The type is int. Will print "value"
}

ただし、必要なことを通知する方法がわからないf(int&)ため、これにはあまり実用的ではありません。C++のオーバーロードがどのように機能するかを明確にしようとしています。

于 2011-05-02T13:06:42.823 に答える
2

より識別可能な名前を選択することで、コンパイラーと関数のユーザーを少し助けることができます。

Container Removed( const Container& c, size_t index );
void Remove( Container& c, size_t index );

不変バージョンに追加constすると、ユーザーが命令型バリアントを誤って呼び出すことも防止されます(コンパイラーは、少なくともconstコンテナーでは許可しません)。

于 2011-05-02T13:04:52.353 に答える
1

参照/値による受け渡しは、関数のオーバーロードを決定するために使用されません。これは、コンパイラがどちらが必要かを知る方法がないためです。どちらも、パラメーターとして渡される値に等しく適切に一致します。また、他の人が指摘しているように、戻り値の型は考慮されません。

于 2011-05-02T12:56:08.067 に答える