8.9.1 在数值类中重载运算符(1)
首先定义一个以英尺和英寸表示长度的类,然后以此为基础,示范如何为数值类实现运算符重载。加法运算符似乎是个不错的起点,下面就是包括加法运算符函数的数值类Length:
- value class Length
- {
- private:
- int feet; // Feet component
- int inches; // Inches component
-
- 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"; }
-
- // Addition operator
- Length operator+(Length len)
- {
- int inchTotal = inches+len.inches+inchesPerFoot*(feet+len.feet);
- return Length(inchTotal/inchesPerFoot, inchTotal%inchesPerFoot);
- }
- };
常量inchesPerFoot是静态的,因此可以直接被类的静态和非静态函数成员使用。我们将inchesPerFoot声明为initonly意味着该常量不能被修改,因此可以是类的公有成员。我们还为Length类定义了重写的ToString()函数,这样就可以使用Console::WriteLine()函数将Length对象输出到命令行上。operator+()函数的实现非常简单。该函数返回一个通过组合当前对象和形参len的feet和inches成员而得到的新Length对象。计算的过程首先合并两个长度,结果以英寸为单位,然后根据合并长度得到的英寸数,为新对象计算Length类构造函数的实参。
下面的代码段可以练习新的加法运算符函数的使用:
- Length len1 = Length(6, 9);
- Length len2 = Length(7, 8);
- Console::WriteLine(L"{0} plus {1} is {2}", len1, len2, len1+len2);
WriteLine()函数的最后一个实参是两个Length对象的和,因此将调用operator+()函数。结果是新的Length对象,编译器将为该对象调用ToString()函数,因此最后一条语句实际上是下面的语句:
- Console::WriteLine(L"{0} plus {1} is {2}", len1, len2,
- len1.operator+(len2).ToString());
执行该代码段将产生下面的输出:
- 6 feet 9 inches plus 7 feet 8 inches is 14 feet 5 inches
当然,我们可以像下面这样将operator+()函数定义成Length类的静态成员:
- static Length operator+(Length len1, Length len2)
- {
- int inchTotal = len1.inches+len2.inches+inchesPerFoot*
- (len1.feet+len2.feet);
- return Length(inchTotal/inchesPerFoot, inchTotal%inchesPerFoot);
- }
- }
形参是两个Length对象,它们将加到一起产生新的Length对象。因为operator+()函数现在是类的静态成员,所以完全有权访问两个实参Length对象的私有成员feet和inches。C++(www.cppentry.com)/CLI类不允许友元函数存在,外部函数无权访问类的私有成员,因此我们没有其他实现加法运算符的可能性。
因为我们不打算处理面积,所以Length对象的乘法实际上仅当长度乘以数值时才有意义。乘法运算符可以作为类的静态成员实现,但我们将在类外部定义该函数。Length类现在如下所示:
- value 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"; }
-
- // Addition operator
- Length operator+(Length len)
- {
- int inchTotal = inches+len.inches+inchesPerFoot*(feet+len.feet);
- return Length(inchTotal/inchesPerFoot, inchTotal%inchesPerFoot);
- }
-
- static Length operator*(double x, Length len);
- // Pre-multiply by a double value
- static Length operator*(Length len, double x);
- // Post-multiply by a double value
- };