设为首页 加入收藏

TOP

8.4.2 实现对运算符的完全支持
2013-10-07 12:31:17 来源: 作者: 【 】 浏览:64
Tags:8.4.2 实现 运算 符的 完全 支持

8.4.2  实现对运算符的完全支持

使用前面实现的operator>()运算符函数,我们仍然有许多事情不能做。用CBox对象指定问题的解决方案可能涉及像下面这样的语句:

  1. if(aBox > 20.0)  
  2. // Do something... 

函数不会处理这里的表达式。如果试图使用比较CBox对象与数值的表达式,那么将得到一条出错消息。为了支持该功能,需要编写另一个版本的operator>()函数作为重载函数。

要支持刚刚看到的表达式类型非常容易。类定义内的成员函数声明将如下所示:

  1. // Compare a CBox object with a constant  
  2. bool operator>(const double& value) const; 

该语句应出现在类定义中,>运算符的右操作数对应于这里的函数形参。作为左操作数的CBox对象是由隐式指针this传递的。

该重载运算符的实现同样很容易,函数体内只有一条语句:

  1. // Function to compare a CBox object with a constant  
  2. bool CBox::operator>(const double& value) const  
  3. {  
  4. return this->Volume() > value;  

没有比这更简单的事情了,不是吗?但使用>运算符处理CBox对象仍然存在问题。我们希望写出下面这样的语句:

  1. if(20.0 > aBox)  
  2. // do something... 

有人可能认为,通过实现接受double类型右实参的operator<()运算符函数,然后相应改写上面这条语句,同样可以完成相同的功能,这么说非常正确。实际上无论如何,实现<运算符都是比较CBox对象所必需的。但是,在实现对某种对象类型的支持时,我们不应该人为限制在表达式中使用这种对象的方式。对象的使用应该尽可能自然。现在的问题是如何来做。

成员运算符函数总是以左边的实参作为指针this。因为本例中左边的实参是double类型,所以我们不能以成员函数的形式实现该运算符。剩下的只有两种选择:普通函数或友元函数。我们不需要访问CBox类的private成员,所以该函数不必是友元函数。因此,我们可以将左操作数属于double类型的重载>运算符实现为普通函数。由于该函数不是成员函数,其原型当然应该放在类定义的外部:

  1. bool operator>(const double& value, const CBox& aBox); 

该函数的实现如下:

  1. // Function comparing a constant with a CBox object  
  2. bool operator>(const double& value, const CBox& aBox)  
  3. {  
  4. return value > aBox.Volume();  

正如前面曾经看到的那样,普通函数(就这一点而论也包括友元函数)使用直接成员选择运算符和对象名访问对象的成员。当然,普通函数只能访问公有成员。成员函数Volume()是公有的,因此这里使用该函数没有什么问题。

如果CBox类没有公有函数Volume(),我们可以直接使用能够访问私有数据成员的友元函数,或者提供一组返回私有数据成员数值的成员函数,然后在普通函数中使用这些函数来实现比较功能。

试一试:完成>运算符的重载

我们可以在示例中将这些放在一起,以说明实际的工作过程:

  1. // Ex8_04.cpp  
  2. // Implementing a complete overloaded 'greater than' operator  
  3. #include <iostream>         // For stream I/O  
  4. using std::cout;  
  5. using std::endl;  
  6.  
  7. class CBox  // Class definition at global scope  
  8. {  
  9. public:  
  10. // Constructor definition  
  11. CBox(double lv = 1.0, double wv = 1.0, double hv = 1.0):  
  12. m_Length(lv), m_Width(wv), m_Height(hv)  
  13. {  
  14. cout << endl << "Constructor called.";  
  15. }  
  16.  
  17. // Function to calculate the volume of a box  
  18. double Volume() const  
  19. {  
  20. return m_Length*m_Width*m_Height;  
  21. }  
  22.  
  23. // Operator function for 'greater than' that  
  24. // compares volumes of CBox objects.  
  25. bool operator>(const CBox& aBox) const  
  26. {  
  27. return this->Volume() > aBox.Volume();  
  28. }  
  29.  
  30. // Function to compare a CBox object with a constant  
  31. bool operator>(const double& value) const  
  32. {  
  33. return this->Volume() > value;  
  34. }  
  35.  
  36. // Destructor definition  
  37. ~CBox()  
  38. { cout << "Destructor called." << endl;}  
  39.  
  40. private:  
  41. double m_Length;            // Length of a box in inches  
  42. double m_Width;                 // Width of a box in inches  
  43. double m_Height;            // Height of a box in inches  
  44. };  
  45.  
  46. int operator>(const double& value, const 
    CBox& aBox); // Function prototype  
  47.  
  48. int main()  
  49. {  
  50. CBox smallBox(4.0, 2.0, 1.0);  
  51. CBox mediumBox(10.0, 4.0, 2.0);  
  52.  
  53. if(mediumBox > smallBox)  
  54. cout << endl 
  55. << "mediumBox is bigger than smallBox";  
  56.  
  57. if(mediumBox > 50.0)  
  58. cout << endl 
  59. << "mediumBox capacity is more than 50";  
  60. else  
  61. cout << endl 
  62. << "mediumBox capacity is not more than 50";  
  63.  
  64. if(10.0 > smallBox)  
  65. cout << endl 
  66. << "smallBox capacity is less than 10";  
  67. else  
  68. cout << endl 
  69. << "smallBox capacity is not less than 10";  
  70.  
  71. cout << endl;  
  72. return 0;  
  73. }  
  74.  
  75. // Function comparing a constant with a CBox object  
  76. int operator>(const double& value, const CBox& aBox)  
  77. {  
  78. return value > aBox.Volume();  

示例说明

注意普通版本operator>()函数的原型所处的位置。该原型需要跟在类定义后面,因为其形参列表中要引用CBox对象。如果我们将其放在类定义前面,则该示例将不能编译。

有一种将其放在程序文件开头#include语句后面的方法:使用未完成的类声明。这样该函数的原型就可以放在类定义之前,声明语句如下所示:

  1. class CBox; // Incomplete class declaration  
  2. int operator>(const double& value, CBox& aBox);     // Function prototype 

未完成的类声明告诉编译器CBox是一个类,这足以使编译器正确处理第二行的函数原型,因为它现在知道CBox是后面将要定义的用户定义类型。

如果有两个类,而每个类都有一个指针成员指向另一个类的对象,在此类情形中我们同样需要上述机制。这两个类都要求另一个类首先被声明,通过使用未完成的类声明就可以打破这样的僵局。

该示例的输出如下:

  1. Constructor called.  
  2. Constructor called.  
  3. mediumBox is bigger than smallBox  
  4. mediumBox capacity is more than 50  
  5. smallBox capacity is less than 10  
  6. Destructor called.  
  7. Destructor called. 

在构造函数因对象smallBox和mediumBox的声明而输出消息之后,我们从三条if语句中得到三行输出,每条语句都像我们预期的那样工作。其中第一条语句调用属于类成员的运算符函数,比较CBox类的两个对象。第二条语句调用形参类型为double的成员函数。第三条if语句中的表达式调用以普通函数形式实现的运算符函数。

两个属于类成员的运算符函数亦可以普通函数的形式实现,因为它们只需要访问公有成员函数Volume()。

注意:

以实现大于运算符的相同方法,我们可以实现任何比较运算符。它们仅仅在次要细节方面不同,大体的实现方法则完全相同。

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇8.5.3 使用有多个形参的类模板 下一篇8.3.3 类和结构中的联合

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: