C++对于“真假值表达式”采用所谓的“骤死式”评估方式。意思是一旦该表达式的真假值确定,即使表达式中还有部分尚未检验,整个评估工作仍告结束。
如果在global scope或是在每个class内对operator&&和operator||两函数进行重载工作,那么“函数调用 语义”会取代“骤死式 语义”。
也就是说,下面这个式子:
if(expression1 && expression2) ...
会被编译器视为以下两者之一:
if(expression1.operator&&(expression2)) ...
//假设operator&&是个member function
if(operator&&(expression1,expression2)) ...
//假设operator&&是个全局函数
这将产生重大的区别:
1.当函数调用动作被执行,所有参数值都必须评估完成,所以当我们调用operator&&和operator||时,两个参数都已评估完成。换句话说没有什么骤死式语义。
2.C++语言规范并未明确定义函数调用动作中各参数的评估顺序,所以没办法知道expression1和expression2哪个会先被评估。
所以,如果你将&&和||重载,就没有办法提供程序员预期的某种行为模式。所以请不要重载&&或||。
C++同样也有一些规则来定义逗号操作符(,)面对内建类型的行为。表达式中如果内含逗号,那么逗号左侧会先被评估,然后逗号的右侧再被评估;最后,整个逗号表达式的结果以逗号右侧的值为代表。
如果把操作符写成一个non-member function,你绝对无法保证左侧表达式一定比右侧表达式更早被评估,因为两个表达式都被当做函数调用时的自变量,传递给该操作符函数,而你无法控制一个函数的自变量评估顺序。
而将操作符写成一个member function,你仍然不能保证逗号操作符的左操作数会先被评估,因为编译器并不强迫做这样的事情。所以不要轻率地将它重载。
你不能重载以下操作符:
. .* :: ?:
new delete sizeof typeid
static_cast dynamic_cast const_cast reinterpret_cast
你可以重载的操作符有:
operator new operator delete
operator new[] operator delete[]
+ - * / % ^ & | ~ ! = < > += -= *= /= %=
^= &= |= << >> >>= == != <= >= && ||
++ – , ->* -> () []
而只因为可以重载这些操作符,就毫无理由地去进行,是没有道理的。
如果你没有什么好理由将某个操作符重载,就不要去做。