3

この C++ の質問はかなり基本的で一般的なようですが、それでも誰かに答えてもらいたいです。

1) 可変長引数を持つ関数とオーバーロードされた関数の違いは何ですか? 2) 可変長引数を持つ関数と、同様の引数を持つ別の同じ名前の関数がある場合、問題が発生しますか?

4

4 に答える 4

7

2)次のことですか?

int mul(int a, int b);
int mul(int n, ...);

最初の整数に2つの整数を掛けると仮定しましょう。n2番目は、var-argsによって渡された整数を乗算します。f(1, 2)「省略記号」を介して渡される引数は可能な限り高いコストに関連付けられているため、で呼び出されることはあいまいではありません。ただし、同じタイプのパラメーターに引数を渡すと、コストが可能な限り低くなります。したがって、この呼び出しは確実に最初の関数に解決されます:)


過負荷解決では、同じ位置の引数とパラメーターの変換のみが比較されることに注意してください。あるパラメータペアのいずれかの関数に勝者がいる場合、それは一生懸命失敗します。例えば

int mul(int a, int b);
int mul(double a, ...);

最初の整数が2つの整数を乗算し、2番目の整数が。で終了するdoubleのリストを乗算するとします0.0。このオーバーロードセットには欠陥があり、によって呼び出されるとあいまいになります

mul(3.14, 0.0); 

これは、2番目の関数が最初の引数に勝ちますが、最初の関数が2番目の引数に勝つためです。2番目の引数の変換コストが最初の関数の最初の引数のコストよりも2番目の関数の方が高いことは問題ではありません。そのような「クロス」勝者の状況が決定されると、そのような2人の候補者の募集はあいまいになります。

于 2009-10-14T15:05:18.367 に答える
1

オーバーロードされた関数は、パラメーターの型に応じて正しいものが選択され、まったく異なる型のパラメーターを持つことができます。

可変長の引数には、少なくとも 1 つのパラメーターが存在する必要があります。また、次のパラメータの型を「予測」するためのメカニズムも必要であり ( で説明する必要があるためva_arg())、基本型 (つまり、整数、浮動小数点、またはポインタ) である必要があります。ここでの一般的な手法は、「フォーマット文字列」( 、printf()などscanf())、または「タグ リスト」(パラメーター リストのすべての奇数要素は、次の偶数要素の型を示す列挙型であり、パラメーターの終わりを示すゼロの列挙型) です。リスト)。

一般的に言えば、オーバーロードは C++ の方法です。C++ の可変長引数リストに似たものが本当に必要になった場合、たとえば、さまざまな数と型の引数を便利にチェーンするために、C++ ストリーム (連結された "<<" と ">>"s) がどのように機能するかを検討してください。

class MyClass {
    public:
        MyClass & operator<<( int i )
        {
            // do something with integer
            return *this;
        }

        MyClass & operator<<( double d )
        {
            // do something with float
            return *this;
        }
};

int main()
{
    MyClass foo;
    foo << 42 << 3.14 << 0.1234 << 23;
    return 0;
}
于 2009-10-14T15:15:24.163 に答える
1

1)オーバーロードされた関数には、さまざまなプロトタイプと実装の地獄が必要です。また、タイプセーフになります。
2)はい、コンパイラは呼び出す必要がある関数を認識できないため、問題が発生します。これについて警告する場合としない場合があります。そうしないと、見つけにくいバグが発生する可能性があります。

于 2009-10-14T15:00:52.453 に答える
0

これはかなり一般的なものであり、Goz はすでにいくつかのポイントをカバーしています。さらにいくつかの:

1) POD オブジェクト以外のものを渡すと、可変引数リストは未定義の動作をします。オーバーロードされた関数は、あらゆる種類のオブジェクトを受け取ることができます。

2) オーバーロード セットの 1 つのメンバーが可変引数リストを取る場合、あいまいさが生じる可能性があります。繰り返しますが、それがなくてもあいまいさを持つことができます。ただし、可変引数リストは、より多くの状況であいまいさを生み出す可能性があります。

最初のポイントは非常に深刻なものです。ほとんどの実用的な目的では、可変引数リストを純粋に C++ の「レガシー」アイテムとしてレンダリングし、新しいコードでの使用を検討するものではありません。最も一般的な代替手段は、代わりにオーバーロードされた演算子をチェーンすることです (たとえば、iostream の挿入/抽出と printf/scanf の比較)。

于 2009-10-14T15:13:46.343 に答える