C++ Primer 5th notes (chap 14 overload operation and type conversion) ambiguity type conversion

1. There will be ambiguity in two situations:

1.1 Class A defines a conversion constructor that accepts Class B objects, while Class B defines a type conversion operator whose conversion target is Class 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&)) ???

If you really want to execute the above call, the call needs to be displayed:

A a1 = f(b.operator A());
A a2 = f(A(b));

1.2 The class defines multiple type conversion rules, and the types involved in these conversions themselves can be linked by other type conversions.

Multiple type conversions marked as built-in types

 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)

The above conversion will cause ambiguity because there is no best match.

short s = 42;
A a3(s); //使用 A::A(int),因为short转换成int由于short转换成double

2. Design principles

  • Do not define the same type conversion for two classes, and do not define two or more conversion sources or conversion targets in a class that are conversions of arithmetic types.
  • If the class contains one or more type conversions, you must ensure that there is only one conversion method between the class type and the target type, otherwise, there may be ambiguity. eg. The most typical example is the arithmetic operator.
  • When we use two user-defined type conversions, if there is a standard type conversion before or after the conversion function, the standard type conversion will determine which is the best match
  • In addition to the explicit conversion to the bool type, the definition of type conversion functions should be avoided as much as possible and the "obviously correct" non-explicit constructors should be restricted as much as possible.

3. Overloaded functions and conversion constructors

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));	//正确,显示的指明调用
  • If you need a constructor or a forced type conversion to change the type of the actual parameter when calling an overloaded function, this usually means that the program design is inadequate. ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????

4. Overloaded functions and user-defined type conversion

When calling overloaded functions, if there are more than one type conversions and they are different from each other, the call is ambiguous. Even if one call requires additional standard type conversion and the other call can match exactly, the compiler will prompt an error.

struct E
{
    
    
	E(double){
    
    }
};
manip(10);	//二义性错误,含义是manip(C(10))还是manip(E(10)) 

[Quote]

[1] Code classTypeExchange.h

Guess you like

Origin blog.csdn.net/thefist11cc/article/details/114210208