8.4.1 实现重载的运算符
为了给某个类实现重载的运算符,我们必须编写特殊的函数。假设在类定义内重载>运算符的函数是CBox类的成员,则该函数的声明如下所示:
- class CBox
- {
- public:
- bool operator>(CBox& aBox) const; // Overloaded 'greater than'
-
- // Rest of the class definition...
- };
这里的单词operator是个关键字。该关键字结合运算符符号或名称,本例中是>,将定义一个运算符函数。本例中的函数名是operator>()。在运算符函数的声明中,关键字和运算符之间有无空格都行,前提是没有歧义。歧义出现在运算符是名称而非符号的时候,比如new或delete。如果写成不加空格的operatornew和operatordelete,则它们都是合法的普通函数名。因此,如果要编写这些运算符的运算符函数,则必须在关键字operator和运算符名称之间加个空格。注意,我们将函数声明为const,因为该函数不修改本类的数据成员。
在operator>()运算符函数中,运算符的右操作数由函数形参定义,左操作数由this指针隐式定义。因此,如果有下面这条if语句:
- if(box1 > box2)
- cout << endl << "box1 is greater than box2";
则括弧中的表达式将调用重载的运算符函数,它与下面这个函数调用等价:
- box1.operator>(box2);
表达式中的CBox对象与运算符函数形参之间的对应关系如图8-3所示。
|
| (点击查看大图)图 8-3 |
下面介绍operator>()函数的工作原理:
- // Operator function for 'greater than' which
- // compares volumes of CBox objects.
- bool CBox::operator>(const CBox& aBox) const
- {
- return this->Volume() > aBox.Volume();
- }
该函数使用引用形参,以避免被调用时不必要的复制开销。因为该函数不需要修改调用它的对象,所以可将其声明为const。如果不这样做,我们将根本不能使用该运算符比较CBox类型的const对象。
return表达式使用成员函数Volume()计算this指向的CBox对象的体积,然后使用基本运算符>,将结果与对象aBox的体积进行比较。基本运算符>返回int(而非bool)类型的数值,因此如果指针this指向的对象比作为引用实参传递的对象aBox的体积大,则返回1,否则返回0。比较结果将自动转换为该运算符函数的返回类型bool。
试一试:运算符重载
我们可以通过如下示例练习如何使用operator>()函数:
- // Ex8_03.cpp
- // Exercising the overloaded 'greater than' operator
- #include <iostream> // For stream I/O
- using std::cout;
- using std::endl;
-
- class CBox // Class definition at global scope
- {
- public:
- // Constructor definition
- CBox(double lv = 1.0, double wv = 1.0, double hv = 1.0):
- m_Length(lv), m_Width(wv), m_Height(hv)
- {
- cout << endl << "Constructor called.";
- }
-
- // Function to calculate the volume of a box
- double Volume() const
- {
- return m_Length*m_Width*m_Height;
- }
-
- bool operator>(const CBox& aBox) const;
// Overloaded 'greater than' -
- // Destructor definition
- ~CBox()
- {
- cout << "Destructor called." << endl;
- }
-
- private:
- double m_Length; // Length of a box in inches
- double m_Width; // Width of a box in inches
- double m_Height; // Height of a box in inches
- };
-
- // Operator function for 'greater than' that
- // compares volumes of CBox objects.
- bool CBox::operator>(const CBox& aBox) const
- {
- return this->Volume() > aBox.Volume();
- }
-
- int main()
- {
- CBox smallBox(4.0, 2.0, 1.0);
- CBox mediumBox(10.0, 4.0, 2.0);
- CBox bigBox(30.0, 20.0, 40.0);
-
- if(mediumBox > smallBox)
- cout << endl
- << "mediumBox is bigger than smallBox";
-
- if(mediumBox > bigBox)
- cout << endl
- << "mediumBox is bigger than bigBox";
- else
- cout << endl
- << "mediumBox is not bigger than bigBox";
-
- cout << endl;
- return 0;
- }
示例说明
operator>()运算符函数的原型出现在类的public部分。由于函数定义在类定义外部,因此该函数默认不是内联函数。这样安排是非常随意的。我们完全可以将函数定义放在类定义中原型的位置,这种情况下将不需要在函数名前面用CBox::加以限定。我们记得,当函数成员在类定义外部定义时,为了告诉编译器该函数是CBox类的成员,必须用类名进行限定。
main()函数中有两条对类成员使用>运算符的if语句,它们将自动调用我们实现的重载运算符。如果想确认这一点,那么可以给运算符函数添加一条输出语句。该示例的输出如下:
- Constructor called.
- Constructor called.
- Constructor called.
- mediumBox is bigger than smallBox
- mediumBox is not bigger than bigBox
- Destructor called.
- Destructor called.
- Destructor called.
输出证实,使用运算符函数的if语句工作正常,因此直接用CBox对象表示CBox问题的解决方案开始成为很现实的命题。