【C++语法】关于operator[]重载的注意点

来源:互联网 发布:free mobile java韩国 编辑:程序博客网 时间:2024/04/28 16:46
【C++语法】关于operator[]重载的注意点
今天在书上注意到这样一段代码:
#include <iostream>#include <cassert>#include <string>using namespace std;template <class type, int dim>class Point{public:Point();Point(type coords[dim]){for (int index = 0; index < dim; index++){_coords[index] = coords[index];}}type& operator[](int index){assert(index < dim && index >= 0);return _coords[index];}type operator[](int index)const{assert(index < dim && index >= 0);return _coords[index];}private:type _coords[dim];};template <class type, int dim>ostream& operator<<(ostream &os, const Point<type, dim> &pt){os << "(";for (int ix = 0; ix < dim - 1; ix++)os << pt[ix] << ", ";os << pt[dim - 1];os << ")";return os;}
一开始挺不明白为何重载operator[]两次,而且二者的区别仅有返回值和函数声明const与非const的区别。

我在两个函数体内添加不同的输出语句,再补充如下main函数:
int main(){string s[3] = { "1", "2", "3" };Point<string, 3> p(s);cout << p;}
最终结果发现只有第二个重载函数被调用,即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函数的返回值用引用。只实现一次重载,在某些情况下是会报错的。
0 0