有关C++中类类型转换操作符总结(必看篇)

2020-01-06 16:21:37王振洲

第三个调用具有二义性。没有构造函数完全匹配于 long。使用每一个构造函

数之前都需要对实参进行转换:

1. 标准转换(从 long 到double)后跟 SmallInt(double)。

2. 标准转换(从 long 到int)后跟 SmallInt(int)。

这些转换序列是不能区别的,所以该调用具有二义性。

当两个类定义了相互转换时,很可能存在二义性:


class Integral;

class SmallInt {

public:

SmallInt(Integral);// convert from Integral to SmallInt

};

class Integral {

public:

operatorSmallInt() const; // convert from Integral to SmallInt 

};

 

void compute(SmallInt);

Integral int_val;

compute(int_val); // error: ambiguous

实参 int_val 可以用两种不同方式转换为 SmallInt 对象,编译器可以使

用接受 Integral 对象的构造函数,也可以使用将 Integral 对象转换为

SmallInt 对象的 Integral 转换操作。因为这两个函数没有高下之分,所以这

个调用会出错。

在这种情况下,不能用显式类型转换来解决二义性——显式类型转换本身既可以使用转换操作又可以使用构造函数,相反,需要显式调用转换操作符或构造函数:


compute(int_val.operator SmallInt()); // ok: useconversion operator

compute(SmallInt(int_val)); // ok: use SmallInt constructor

改变构造函数以接受 const Integral 引用:


class SmallInt {

public:

SmallInt(constIntegral&);

};

则对compute(int_val) 的调用不再有二义性!原因在于使用 SmallInt构造函数需要将一个引用绑定到 int_val,而使用 Integral 类的转换操作符可以避免这个额外的步骤。这一小小区别足以使我们倾向于使用转换操作符。

显式强制转换消除二义性


class SmallInt {

public:

// Usually it is unwise to define conversions tomultiple

arithmetic types

operatorint() const { return val; }

operatordouble() const { return val; }

// ...

private:

std::size_tval;

};

void compute(int);

void compute(double);

void compute(long double);

SmallInt si;

compute(si); // error: ambiguous


可以利用显式强制转换来消除二义性:

compute(static_cast<int>(si)); // ok: convertand call compute(int)


显式构造函数调用消除二义性


class SmallInt {

public:

SmallInt(int= 0);

};

class Integral {

public:

Integral(int= 0);

};

void manip(const Integral&);

void manip(const SmallInt&);

manip(10); // error: ambiguous

 

可以用显示构造函数消除二义性:


manip(SmallInt(10)); // ok: call manip(SmallInt)

manip(Integral(10)); // ok: call manip(Integral)