重载operator[]的注意事项

【C++语法】关于operator[]重载的注意点
今天在书上注意到这样一段代码:
  1. #include <iostream>
  2. #include <cassert>
  3. #include <string>
  4. using namespace std;
  5. template < class type, int dim>
  6. class Point
  7. {
  8. public:
  9. Point();
  10. Point(type coords[dim])
  11. {
  12. for ( int index = 0; index < dim; index++)
  13. {
  14. _coords[index] = coords[index];
  15. }
  16. }
  17. type& operator[]( int index)
  18. {
  19. assert(index < dim && index >= 0);
  20. return _coords[index];
  21. }
  22. type operator[]( int index) const
  23. {
  24. assert(index < dim && index >= 0);
  25. return _coords[index];
  26. }
  27. private:
  28. type _coords[dim];
  29. };
  30. template < class type, int dim>
  31. ostream& operator<<(ostream &os, const Point<type, dim> &pt)
  32. {
  33. os << "(";
  34. for (int ix = 0; ix < dim - 1; ix++)
  35. os << pt[ix] << ", ";
  36. os << pt[dim - 1];
  37. os << ")";
  38. return os;
  39. }
一开始挺不明白为何重载operator[]两次,而且二者的区别仅有返回值和函数声明const与非const的区别。

我在两个函数体内添加不同的输出语句,再补充如下main函数:
  1. int main()
  2. {
  3. string s[ 3] = { "1", "2", "3" };
  4. Point< string, 3> p(s);
  5. cout << p;
  6. }
最终结果发现只有第二个重载函数被调用,即const的那一个。我注释掉第二个重载函数,运行,编译器报错:error C2678: 二进制“[”: 没有找到接受“const Point<std::string,3>”类型的左操作数的运算符(或没有可接受的转换)。
注意到错误信息中的const Point<std::string,3>,由于它带有const,所以只能调用const函数这是C++语法规则,是知道的,但是const Point<std::string,3>指的哪个const Point<std::string,3>呢?仔细排查后,只可能是operator<<()参数里的那个。
尝试着将函数声明改为ostream& operator<<(ostream &os, Point<type, dim> &pt),也就是去掉了const,运行发现通过了,并且之前加在第一个重载函数的语句也输出来,说明第一个重载函数被调用了。我取注掉之前的注释,运行,发现这次依旧是第一个重载函数被调用,而不是第二个了。


结论及注意事项
C++中,const类型对象只能调用const成员函数(上面提过的),但非const类型对象对于重载了const和非const的函数,会优先调用非const函数。这也提醒我们对于确定不想改变的变量,一定要定义为const类型,防止调用了某个非const的成员函数改变了对象数据却没有发现!
一个类重载operator[]()函数时,要重载operator[]两次,一个是const函数,一个是非const函数。const函数的返回值用按值传递,非const函数的返回值用引用。只实现一次重载,在某些情况下是会报错的。

1、请注意operator[]下标操作符只能作为类的成员函数,同时在定义类的下标操作符时请定义两个版本,以适应const对象和非const对象

2、小心operator[]带来的陷阱。在重载时必须把这部分陷阱考虑进去,以防止此付出的代价。

猜你喜欢

转载自blog.csdn.net/u010248077/article/details/80951467