函数重载注意点

一、为什么不要重载 && 和 || 操作符

1
2
3
4
int a1 = 1;
int a2 = 0;
if (a1 || a2++)
if (a2 && a1++)
  • 如上,第一个 if 判断条件因为 a1 为真,所以整个逻辑或就是真,不再执行 a2++
  • 第二个 if 判断条件因为 a2 为假,导致整个逻辑与为假,不再执行 a1++

如果重载 || 或 && 会是什么情况呢?

  • 首先理论上,操作符重载是靠函数重载来完成。操作数作为函数参数传递。C++ 的函数参数都会被求值,因此可能会造成语义错误
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Test {
private:
int val;
public:
explicit Test(int val) : val(val) {}
bool operator||(const Test& obj) const {
return val || obj.val;
}
bool operator&&(const Test& obj) const {
return val && obj.val;
}
};
t1 && (t1+t2) 这个代码的调用本质是: t1.operator&&( t1.operator+(t2) )
其中 t1.operator+(t2) 是作为函数参数传递的,因为这个表达式不管 t1 是否是真假,都会计算求值。
  • 因此重载之后可能会造成语义错误

二、为什么不要重载逗号表达式

  • 对于逗号表达式,逗号左侧会先被评估,然后逗号的右侧再被评估;最后,整个表达式的结果以逗号右侧的值为代表。
  • 如果重载了逗号表达式,就无法保证左侧表达式会比右侧表达式先被评估,编译器无法作出保证

三、哪些操作符不可以重载

如下的操作符都不建议重载

1
2
.、.*、 ::、 ?:、 new、 delete、 sizeof、 typeif
static_cast、dynamic_cast、const_cast、reinterpret_cast

重载的目的就是为了让程序更容易被阅读、被修改、被理解。如果没有好的理由重载某个操作符,就不要重载。