【C++语法】关于operator[]重载的注意点
今天在书上注意到这样一段代码:
-
-
-
-
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;
-
}
-
我在两个函数体内添加不同的输出语句,再补充如下main函数:
-
int main()
-
{
-
string s[ 3] = { "1", "2", "3" };
-
Point< string, 3> p(s);
-
cout << p;
-
}
注意到错误信息中的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[]带来的陷阱。在重载时必须把这部分陷阱考虑进去,以防止此付出的代价。