15 More Effectic C++ ——条款21/22(重载防止隐式类型转换/使用复合操作符)

1 看不见的隐式类型转换

当构造函数只有一个,编译器会利用构造函数进行隐式类型转换。如下面所示:

class UInt {
	public:
		UInt();
		UInt(int value);
}
UInt a = 0, b(0), c = 1; // 隐式转换:int变成UInt类型
UInt d = 1 + a; // 隐式类型转换

这种隐式类型转换十分危险,当有多种类似"UInt(int value)"函数被声明时,比如“UInt(SomeType value)”,就会造成比较严重的逻辑错误——误调用隐式类型转换。

为了消除这种危险,可以采用以下两种方法。但是,不推荐使用大量重载函数,会使软件更难维护。

方法1:使用explicit关键字

explicit关键字需要用户明确指出类型转换。

class UInt {
	public:
		Unit();
		explicit UInt(int a);
}
UInt a = 1 + b; //错误,没有明确指出1的类型。
UInt a = UInt(1) + b; //正确,明确指出类型。
方法2:利用函数重载

如下,重载函数通过不同函数签名来识别。较低版本中,函数签名只依据传入参数的不同来识别。

const UInt operator+(int lhs, const UInt& rhs);
const UInt operator+(const UInt& lhs, int rhs);
const UInt operator+(const UInt& lhs, const UInt& rhs);
// 以上都正确,下面错误
const UInt operator+(int lhs, int rhs); // 重载的和库中的签名一致,错误。

2 复合操作符与其单独形式

C++允许我们重载+, -, *, /四种操作符,他们对应的复合操作符为:+=, -=, *=, /=。这8个操作符允许用户进行重载。由于单独操作符会涉及如下两个步骤,复合操作符只涉及第1步,因此具体运算可以直接使用复合操作符。

1,运算
2,获得运算结果,并存储在临时变量中,返回临时变量。

具体代码如下:

class MyClass {
	public:
		MyClass& operator += (const MyClass& rhs)
		{
			// do something
			return *this;
		}
}
const MyClass operator + (const MyClass& lhs, const MyClass& rhs)
{
	return MyClass(lhs) += rhs;
}
// 进一步,可以使用template来实现
template<class T>
const T operator +(const T& lhs, const T& rhs)
{
	return T(lhs) += rhs;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值