C# · 12月 20, 2021

C++11显示类型转换

1.隐式类型转换的问题

隐式类型转换是C++一个让人又爱又恨的特性,使用方便,但可能会降低代码可读性,甚至会造成一些十分隐晦的错误。

#include

using namespace std;

class MyInt

{

public:

//单参构造函数

explicit MyInt(int value) :_value(value)

{}

//类型转换操作符

operator bool() const noexcept

{

return _value != 0;

}

//加运算符重载

MyInt& operator+(const MyInt& right)

{

_value += right.getValue();

return *this;

}

int getValue() const

{

return _value;

}

private:

int _value;

};

int main()

{

MyInt myInt1(1);

MyInt myInt2(2);

cout << "myInt1+myInt2=" << myInt1 + myInt2 << endl;

return 0;

}

程序编译运行输出:

myInt1+myInt2=1

虽然程序编译运行没有什么问题,但是两个MyInt对象相加的结果并不是我们期望的数值3,而是1,导致这种隐晦错误的原因是在两个MyInt对象相加后,结果对象myInt1被隐式地转换为bool类型,导致输出数值为1。随着项目代码规模变大,这种由隐式类型转换导致的隐晦错误会越埋越深,越来越难以发现。

2.显示类型转换

为了阻止容易导致隐晦错误的隐式类型转换,C++11引入了explicit关键字作用于自定义的类型转换操作符的功能,禁止隐式类型转换。其用法类似于explicit作用于单参构造函数来避免单参数构造函数被隐式调用造成的隐式类型转换。

//类型转换操作符

explicit operator bool() const noexcept

{

return _value != 0;

}

cout << "myInt1+myInt2=" << myInt1 + myInt2 << endl; //编译出错

当使用explicit关键字修饰bool类型转换操作符时,隐式类型转换将会被阻止,进而引起上面的编译错误,将潜在的隐晦错误暴露于编译阶段,让错误得以提前发现,提前解决。

注意,显式类型转换有一个例外。如果表达式被用作条件,仅限转换到bool,那么显式的operator bool()也可以隐式地进行。“被用作条件”指出现在以下语句:

(1)if、while及do语句的条件部分;

(2)for语句头的条件表达式;

(3)逻辑非运算符(!)、逻辑或运算符(||)、逻辑与运算符(&&)的运算对象;

(4)条件运算符(x ? y : z)的条件表达式。

由于转换到bool一般被用作条件,所以operator bool()一般用explicit来修饰。

参考文献

[1]深入理解C++11[M].显示转换操作符

[2]【C++11】显式转换操作符