8.9.3 在引用类中重载运算符
在引用类中重载运算符基本上与在数值类中重载运算符相同,主要区别在于形参和返回值通常都是句柄。下面介绍作为引用类实现的Length类,然后可以对两个版本作一番比较。
试一试:在引用类中重载运算符
该示例将Length定义成引用类,其中包括一组与数值类版本相同的重载运算符:
- // Ex8_13.cpp : main project file.
- // Defining and using overloaded operator
-
- #include "stdafx.h"
- using namespace System;
-
- ref class Length
- {
- private:
- int feet;
- int inches;
-
- public:
- static initonly int inchesPerFoot = 12;
-
- // Constructor
- Length(int ft, int ins) : feet(ft), inches(ins){ }
-
- // A length as a string
- virtual String^ ToString() override
- { return feet+L" feet " + inches + L" inches"; }
-
- // Overloaded addition operator
- Length^ operator+(Length^ len)
- {
- int inchTotal = inches+len->inches+inchesPerFoot*(feet+len->feet);
- return gcnew Length(inchTotal/inchesPerFoot,
inchTotal%inchesPerFoot); - }
-
- // Overloaded divide operator - right operand type double
- static Length^ operator/(Length^ len, double x)
- {
- int ins = safe_cast<int>((len->feet*inchesPerFoot + len->inches)/x);
- return gcnew Length(ins/inchesPerFoot, ins%inchesPerFoot);
- }
-
- // Overloaded divide operator - both operands type Length
- static int operator/(Length^ len1, Length^ len2)
- {
- return (len1->feet*inchesPerFoot + len1->inches)/
- (len2->feet*
inchesPerFoot + len2->inches); - }
-
- // Overloaded remainder operator
- static Length^ operator%(Length^ len1, Length^ len2)
- {
- int ins = (len1->feet*inchesPerFoot + len1->inches)%
- (len2->feet*inches
PerFoot + len2->inches); - return gcnew Length(ins/inchesPerFoot, ins%inchesPerFoot);
- }
-
- static Length^ operator*(double x, Length^ len);
- //
Multiply - L operand double - static Length^ operator*(Length^ len, double x);
- //
Multiply - R operand double -
- // Pre- and postfix increment operator
- static Length^ operator++(Length^ len)
- {
- Length^ temp = gcnew Length(len->feet, len->inches);
- ++temp->inches;
- temp->feet += temp->inches/temp->inchesPerFoot;
- temp->inches %= temp->inchesPerFoot;
- return temp;
- }
- };
-
- // Multiply operator implementation - left operand double
- Length^ Length::operator*(double x, Length^ len)
- {
- int ins = safe_cast<int>(x*len->inches +x*len->feet*inchesPerFoot);
- return gcnew Length(ins/inchesPerFoot, ins%inchesPerFoot);
- }
-
- // Multiply operator implementation - right operand double
- Length^ Length::operator*(Length^ len, double x)
- { return operator*(x, len); }
-
- int main(array<System::String ^> ^args)
- {
- Length^ len1 = gcnew Length(2,6); // 2 feet 6 inches
- Length^ len2 = gcnew Length(3,5); // 3 feet 5 inches
- Length^ len3 = gcnew Length(14,6); // 14 feet 6 inches
-
- // Use +, * and / operators
- Length^ total = 12*(len1+len2+len3) + (len3/gcnew Length(1,7))*len2;
- Console::WriteLine(total);
-
- // Use remainder operator
- Console::WriteLine(
- L"{0} can be cut into {1} pieces {2} long with {3} left over.",
- len3, len3/len1, len1, len3%len1);
- Length^ len4 = gcnew Length(1, 11); // 1 foot 11 inches
-
- // Use pre- and postfix increment operator
-
- Console::WriteLine(len4++); // Use postfix increment operator
- Console::WriteLine(++len4); // Use prefix increment operator
- Console::WriteLine(len4); // Final value of len4
- return 0;
- }
该示例产生下面的输出:
- 275 feet 9 inches
- 14 feet 6 inches can be cut into 5 pieces 2 feet 6 inches long
- with 2 feet 0 inches left over.
- 1 feet 0 inches
- 2 feet 0 inches
- 2 feet 1 inches
示例说明
与数值类相比,主要区别在于重载运算符函数的形参和返回类型,因此本例使用->运算符,另外Length类型的对象现在是使用gcnew关键字在CLR堆上创建的。此外,重载的递增运算符函数返回一个临时对象,并且没有用引用实参修改原始对象。
重要的是当我们在引用类中重载递增或递减运算符时没有修改原始对象,因为编译器生成的代码依赖于传递给重载函数的对象,原始代码没有修改。当为某个后缀递增或递减运算调用该函数时,用出现它的表达式中的对象生成代码,然后存储返回的对象来替换原始对象。尽管有这些变化,代码仍基本上相同,该运算符函数与上一个示例中一样有效。