重载operator[]的注意事项

xiaoxiao2021-02-28  48

【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函数的返回值用引用。只实现一次重载,在某些情况下是会报错的。

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

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

转载请注明原文地址: https://www.6miu.com/read-2613993.html

最新回复(0)