下标运算符
下标运算符必须是类的成员函数。
下标运算符通常返回访问元素的引用,从而使得下标可以出现在赋值运算符的任意一侧,进一步,最后同时定义下标运算符的常量和非常量版本,当作用于一个常量对象时,下标运算符返回常量的引用以确保不会给返回的对象赋值。
class StrVec
{
public:
std::string& operator[](std::size_t n)
{
return elements[n];
}
const std::string& operator[](std::size_t n) const
{
return elements[n];
}
};
递增和递减运算符
并不要求递增和递减运算符一定是类的成员函数,但是因为这个运算符改变的正好是所操作的对象的状态,所以建议将它们设为成员函数。
递增和递减运算符应该同时定义前置和后置两个版本。
class StrBlobPtr
{
public:
//前置版本
StrBlobPtr &operator++();
StrBlobPtr &operator--();
};
StrBlobPtr & StrBlobPt::operator++()
{
check(curr,"increment past end of StrBlobPtr");
++cur;
return *this;
}
StrBlobPtr & StrBlobPt::operator--()
{
--cur;
check(curr,"increment past end of StrBlobPtr");
return *this;
};
区分前置和后置运算符
普通的重载形式无法区分是前置运算还是后置运算,为了解决这个问题,后置版本加上一个额外的不被使用的 int
类型参数:
class StrBlobPtr
{
public:
//后置版本
StrBlobPtr &operator++(int);
StrBlobPtr &operator--(int);
};
StrBlobPtr & StrBlobPt::operator++(int)
{
StrBlobPt ret = *this;
++*this;
return ret;
}
StrBlobPtr & StrBlobPt::operator--(int)
{
StrBlobPt ret = *this;
--*this;
return ret;
};
显式的调用后置运算符:
StrBlobPtr p(a);
p.operator++(0); //后置版本
p.operator++(); //前置版本
成员访问运算符
箭头运算符必须是类的成员。
解引用运算符通常也是类的成员,尽管这并非是必须的。
class StrBlobPtr
{
public:
std::string& operator*()const
{
auto p = check(curr,"dereference past end");
return (*p)(curr);
}
std::string* operator->()const
{
return & this->operator*(); //返回解引用结果的地址
}
};