1.次の2つの状況ではあいまいさがあります。
1.1クラスAは、クラスBオブジェクトを受け入れる変換コンストラクターを定義し、クラスBは、変換ターゲットがクラスAである型変換演算子を定義します。
struct B;
struct A
{
A() = default;
A(const B&); //把一个B转换为A
};
struct B{
operator A() const; //也是把B转换为A
}
A f(const A& a) {
return a;
}
B b;
A a = f(b); //二义性错误,含义是 f(B::operator A()) 还是f(A::A(const B&)) ???
上記の呼び出しを本当に実行したい場合は、表示する必要のある呼び出しは次のとおりです。
A a1 = f(b.operator A());
A a2 = f(A(b));
1.2クラスは複数の型変換ルールを定義し、これらの変換に関係する型自体を他の型変換によってリンクできます。
組み込み型としてマークされた複数の型変換
struct A{
//最好不要创建两个转换源都是算术类型的类型转换
A(int = 0);
A(double);
//最好不要创建两个转换对象都是算术类型的类型转换
operator int() const;
operator double() const;
};
void f2(long double);
A a;
f2(a); //二义性错误,含义是 f(A::operator int()),还是f(A::operator double())
long lg;
A a2(lg); //二义性错误,含义是A::A(int) 还是 A::A(double)
上記の変換では、最適な一致がないため、あいまいさが生じます。
short s = 42;
A a3(s); //使用 A::A(int),因为short转换成int由于short转换成double
2.設計原則
- 2つのクラスに同じ型変換を定義しないでください。また、算術型の変換であるクラス内に2つ以上の変換ソースまたは変換ターゲットを定義しないでください。
- クラスに1つ以上の型変換が含まれている場合は、クラス型とターゲット型の間に変換メソッドが1つしかないことを確認する必要があります。そうしないと、あいまいさが生じる可能性があります。たとえば、最も一般的な例は算術演算子です。
- 2つのユーザー定義型変換を使用する場合、変換関数の前後に標準型変換がある場合、標準型変換によってどちらが最適かが判断されます。
- ブール型への明示的な変換に加えて、型変換関数の定義を避け、「明らかに正しい」非明示的なコンストラクターを可能な限り制限する必要があります。
3.オーバーロードされた関数と変換コンストラクター
struct C
{
C(int);
};
struct D
{
D(int);
};
void manip(const C&);
void manip(const D&);
manip(10); //二义性错误,含义是manip(C(10))还是manip(D(10))
manip(C(10)); //正确,显示的指明调用
- オーバーロードされた関数を呼び出すときに引数の型を変更するためにコンストラクターまたは強制型変換が必要な場合、これは通常、プログラムの設計が不十分であることを意味します。
4.オーバーロードされた関数とユーザー定義の型変換
オーバーロードされた関数を呼び出すときに、複数の型変換があり、それらが互いに異なる場合、呼び出しはあいまいです。一方の呼び出しで追加の標準型変換が必要で、もう一方の呼び出しが完全に一致する場合でも、コンパイラーはエラーをプロンプトします。
struct E
{
E(double){
}
};
manip(10); //二义性错误,含义是manip(C(10))还是manip(E(10))
[見積もり]