8.9.1 在数值类中重载运算符(3)
该示例的输出如下:
- 6 feet 9 inches plus 7 feet 8 inches is 14 feet 5 inches
- 2.5 times 7 feet 8 inches is 19 feet 2 inches
- 7 feet 8 inches times 2.5 is 19 feet 2 inches
- The sum of 6 feet 9 inches and 7 feet 8 inches
divided by 2.5 is 5 feet 9 inches
示例说明
Length类中新的运算符重载函数用于处理除法,它允许Length对象除以double类型的数值。令double数值除以Length对象没有明显的意义,因此不需要实现。operator/()函数是作为Length类的另一个静态成员实现的,其定义出现在类定义内部,以便就语法形式与operator*()函数进行比较。通常,我们应该将所有这些函数都定义在类定义内部。
当然,我们可以像下面这样将operator/()函数定义成非静态的类成员:
- Length operator/(double x)
- {
- int ins = safe_cast<int>((feet*inchesPerFoot + inches)/x);
- return Length(ins/inchesPerFoot, ins%inchesPerFoot);
- }
现在,该函数只有一个作为/运算符右操作数的实参。左操作数是this指针(该情况下是隐式指针)引用的当前对象。
我们在4条输出语句中练习运算符的使用,其中只有最后一条是全新的,该语句组合使用了Length对象的+和/重载运算符。在第四条输出语句中,Console::WriteLine()函数的最后一个实参是(len1+len2)/factor,它等价于下面的表达式:
- Length::operator/(len1.operator+(len2), factor) .ToString()
静态operator/()函数的第一个实参是operator+()函数返回的Length对象,第二个实参是除数变量factor。operator/()返回的Length对象调用ToString()函数,从而产生将传递给Console::WriteLine()函数的实参字符串。
我们有可能需要将一个Length对象除以另一个同类对象,然后得到int类型的数值。例如,该功能将使我们能够算出一块长12英尺6英寸的木料可以切成多少块长17英寸的木料。如下所示,我们可以非常容易地实现该功能:
- static int operator/(Length len1, Length len2)
- {
- return
- (len1.feet*inchesPerFoot + len1.inches)/( len2.feet*inchesPerFoot +
- len2.inches);
- }
该函数仅仅返回第一个长度(转换为英寸)除以第二个长度(转换为英寸)的结果而已。
为了使除法运算完整,我们可以添加一个重载%运算符的函数,以确定还有多少余料。该函数的实现如下所示:
- static Length operator%(Length len1, Length len2)
- {
- int ins = (len1.feet*inchesPerFoot + len1.inches)%
- (len2.feet*inchesPerFoot + len2.inches);
- return Length(ins/inchesPerFoot, ins%inchesPerFoot);
- }
在算出len1除以len2产生的余数(以英寸表示)以后,我们将其作为新的Length对象返回。
有了所有这些运算符,我们将完全能够在算术表达式中使用Length对象。我们可以写出像下面这样的语句:
- Length len1 = Length(2,6); // 2 feet 6 inches
- Length len2 = Length(3,5); // 3 feet 5 inches
- Length len3 = Length(14,6); // 14 feet 6 inches
- Length total = 12*(len1 + len2 + len3) + (len3/Length(1,7))*len2;
total的值将是275英尺9英寸。最后一条语句利用了每个数值类都有的赋值运算符以及Length类中的operator*()、operator+()和operator/()函数。运算符重载功能不仅非常强大,而且还相当简单,不是吗?