小天:来个实例说明下,到底是怎么重载的吧。
老田:在讲解实例之前,我们应该先理解运算符是如何重载的,考虑一下在编译器遇到运算符时会发生什么样的情况。我们用相加运算符+作为例子来讲解。假定编译器遇到下面的代码:
int myInteger = 3; uint myUnsignedInt = 2; double myDouble = 4.0; long myLong = myInteger + myUnsignedInt; double myOtherDouble = myDouble + myInteger; //会发生什么情况: long myLong = myInteger + myUnsignedInt; |
编译器知道它需要把两个整数加起来,并把结果赋予long。调用一个方法把数字加在一起时,表达式myInteger + myUnsignedInt是一种非常直观、方便的语法。该方法带有两个参数myInteger和myUnsignedInt,并返回它们的和。所以编译器完成的任务与任何方法调用是一样的——它会根据参数类型查找最匹配的+运算符重载,这里是带两个整数参数的+运算符重载。与一般的重载方法一样,预定义的返回类型不会因为调用的方法版本而影响编译器的选择。在本例中调用的重载方法带两个int类型参数,返回一个int,这个返回值随后会转换为long。
下一行代码让编译器使用+运算符的另一个重载版本:
double myOtherDouble = myDouble + myInteger; |
在这个例子中,参数是一个double类型的数据和一个int类型的数据,但+运算符没有带这种复合参数的重载形式,所以编译器认为,最匹配的+运算符重载是把两个double作为其参数的版本,并隐式地把int转换为double。把两个double加在一起与把两个整数加在一起完全不同,浮点数存储为一个尾数和一个指数。把它们加在一起要按位移动一个double的尾数,让两个指数有相同的值,然后把尾数加起来,移动所得尾数的位,调整其指数,保证答案有尽可能高的精度。
通常情况下,如果编译器找到运算符的重载版本,就调用它的实现代码。如果找不到,就要看看有没有可以用作最佳匹配的其他预定义运算符重载,例如某个运算符重载的参数是其他数据类型,但可以隐式地转换为当前实例。如果编译器找不到合适的运算符重载,就会产生一个编译错误,就像找不到其他方法调用的合适重载版本一样。
本文章为天轰穿原创作品,转载请注明出处及作者。