1

ソースコードにそれ自体を語らせましょう:

MLine::MLine(int x1, int y1, int x2, int y2)
{
}

MLine::MLine(double x1, double y1, double x2, double y2)
{
}

void __fastcall TVctDiag2::PrepareArrowTail(int x, int y)
{
    double length_x1;
    double length_y1;
    MLine *line = new MLine(x, y, x - length_x1, y - length_y1);
}

コンパイラは次のエラーを生成します:

E2015「shapes.h:100のMLine :: MLine(int、int、int、int)」と「shapes.h:110のMLine :: MLine(double、double、double、double)」の間のあいまいさ

明示的なキャストに従うことで、この問題を解決できます。

    MLine *line = new MLine((double)x, (double)y, x - length_x1, y - length_y1);

部分的なキャストでは不十分です。

    MLine *line = new MLine((double)x, y, x - length_x1, y - length_y1);

式での暗黙のキャストのルールについてはかなり混乱しています。誰かがこの行動を説明できますか?式'x--length_x1'および'y--length_y1'のデータ型は何ですか?

4

2 に答える 2

2

式での暗黙のキャストのルールについてはかなり混乱しています。誰かがこの行動を説明できますか?

二項演算子(+-* /など)は、同じタイプのオペランドで機能します(そして、それらのオペランドと同じタイプの結果を返します)。タイプが同じでない場合は、両方のオペランドが同じタイプになるように、一方(通常は両方)がプロモートされます。

式'x--length_x1'および'y--length_y1'のデータ型は何ですか?

X         => int
length_x1 => double

したがって、タイプは同じではありません。したがって、1つのオブジェクトがプロモートされます。この場合、Xはdoubleに昇格します(昇格ルールを調べる理由)。演算子-が適用され、結果はdoubleになります。

ここであなたの表現を見ると:

MLine *line = new MLine(x, y, x - length_x1, y - length_y1);

サブ式をそれらのタイプに置き換えると、次のようになります。

MLine *line = new MLine(<int>, <int>, <double>, <double>);

これで、コンパイラのジレンマを確認できます。コンストラクターのどのバージョンを選択するかを知る方法はありません(どちらも1ラウンドのキャストを適用することで到達できます)。したがって、エラーを生成する必要があります。

于 2012-04-17T09:05:42.303 に答える
1
MLine *line = new MLine((double)x, y, x - length_x1, y - length_y1);

これが機能しない理由は、派生したタイプが次のとおりであるためです。

MLine(double, int, double, double)

これは...

昇進

オペランドが混在する演算では、オペランドが他のタイプに変換される場合があります。浮動小数点型と整数型の操作の場合、整数は最初に浮動小数点型に変換されます。

float f; int i;
f + i;

f + ifloatは、加算が行われる前ににi変換されるため、タイプfloatです。

このプロモーションは...

あいまいさ

完全に一致するものはなく、過負荷の候補はあいまいです。

技術的に(そして単純化して)、C ++コンパイラーは完全一致を使用するか、一連の過負荷候補から最適な一致を選択します。ルールは重要です(1つの測定値は必要な変換の数です)。

いくつかの例を導き出しましょう:

void foo (int) {}
int main () { foo(5.f); }

->候補は1つだけであり、doubleは暗黙的にintに変換できるため、機能します。

#include <iostream>
void foo (int) { std::cout << "foo(int)\n"; }
void foo (float) { std::cout << "foo(float)\n"; }
int main () { foo(5.f); }

->完全に一致するため、2番目のバージョンが使用されます。

#include <iostream>
void foo (int) { std::cout << "foo(int)\n"; }
void foo (float) { std::cout << "foo(float)\n"; }
int main () { foo(5.); }

->注:今回は、を渡しますdouble。両方のオーバーロードには変換が必要であり、完全に一致するわけではないため、コンパイルされません。したがって、候補はあいまいです。

複数のパラメータでも同じです。

#include <iostream>
void foo (int,int) { std::cout << "foo(int,int)\n"; }
void foo (float,float) { std::cout << "foo(float,float)\n"; }
int main () { 
    foo(5.f, 5.f); // exact match with the (float,float) overload
    foo (5, 5);    // exact match with the (int,int) overload
    foo (5, 5.f);  // No exact match, and candidates are ambiguous
}
于 2012-04-17T09:04:46.043 に答える