12.3 可重载的运算符

虽然几乎所有C中的运算符都可以重载,但运算符重载的使用是相当受限制的。特别是不能使用C中当前没有意义的运算符(例如用**代表求幂),不能改变运算符的优先级,不能改变运算符的参数个数。这样限制有意义,否则,所有这些行为产生的运算符只会混淆而不是澄清语意。

下面两个小节给出重载所有“常规”运算符的例子,重载的形式都是最可能用到的。

12.3.1 一元运算符

下面的例子显示了重载所有一元运算符的语法,有全局函数形式(非成员的友元函数)也有成员函数形式。它们将扩充前面给出的类Integer并且增加一个新类byte。具体运算符的含义取决于使用它们的方式,但在设计特殊操作之前要为未来使用这些类的程序员好好想一想。

这里是所有一元函数的目录:

12.3 可重载的运算符 - 图1

12.3 可重载的运算符 - 图2

12.3 可重载的运算符 - 图3

12.3 可重载的运算符 - 图4

函数是根据其参数传递的方法分组的。如何传递和返回参数的指导方针到后面再讲。上面的形式(和下一小节的形式)是典型的使用形式,所以在你自己重载运算符时可以从这些范式开始。

12.3.1.1 自增和自减

重载的++和—运算符有点让人进退维谷,因为我们总是希望能根据它们出现在所作用的对象的前面(前缀)还是后面(后缀)来调用不同的函数。解决方法很简单,但有些人一开始会觉得容易混淆。例如当编译器看到++a(先自增)时,它就调用operator++(a);但当编译器看到a++时,它就调用operator++(a, int)。即编译器通过调用不同的重载函数区别这两种形式。在成员函数版本的OverloadingUnaryOperators.cpp中,如果编译器看到++b,它就产生一个对B:operator++()的调用;如果编译器看到b++,它就产生一个对B:operator++(int)的调用。

用户所见到的是对前缀和后缀版本调用不同的函数。然而,实质上这两个函数调用有着不同的标记,所以它们指向两个不同的函数体。编译器为int参数传递一个哑元常量值(因为这个值永远不被使用,所以它永远不会给出一个标识符)用来为后缀版产生不同的标记。