1.重载操作符必须具有至少一个类类型或枚举类型的操作数(内置类型的操作符含义不能改变);
2.除了函数调用操作符operator()之外,重载操作符时不能使用默认实参;
3.重载之后&&, ||不再具备短路求值特征;
4.作为成员函数的操作符有一个隐含的this形参,限定为第一个操作数;
一般将算数和关系操作符定义为非成员函数,而将赋值操作符定义为成员:
//成员函数
Sales_item& Sales_item::operator += (const Sales_item&);
//非成员函数
Sales_item operator + (const Sales_item&, const Sales_item&);
5.操作符定义为非成员函数时,通常需要将它们设置为所操作类的友元(这样才能访问私有数据成员);
6.赋值(=)、下标([ ])、调用(( ))、和成员访问箭头(->)必须定义为成员函数;
IO操作符必须为非成员函数,类通常将IO操作符设为友元;
7.输入输出操作符重载(必须为非成员函数)
//输出操作符,返回流的引用。
//输出不修改值,所以第二个参数为const引用
ostream& operator << (ostream & out, const ClassType & obj)
{
//doSomething
out<< // ...
return out;
}
//输入操作符,返回流的引用。
//输入修改值,所以第二个参数为非const引用
istream& operator >> (istream & in, ClassType & obj)
{
//doSomething
in>> // ...
//注意需要处理输入错误以及文件结束等情况!
return in;
}
//例子:
istream& operator >> (istream & in, Sales_item & s)
{
double price;
in >> s.isbn >> s.units_sold >> price;
//检测是否输入成功
if (in)
s.revenue = s.units_sold * price;
else
s = Sales_item(); //输入失败,reset to default state
return in;
}
8.算术操作符和关系操作符
// assumes that both objects refer to the same book
//加法返回的是一个右值,而不是引用
Sales_data
operator + (const Sales_data &lhs, const Sales_data &rhs)
{
Sales_data sum = lhs; // copy data members from lhs into sum
sum += rhs; // add rhs into sum,前提是定义了+=操作符
return sum;
}
bool
operator == (const Sales_data &lhs, const Sales_data &rhs)
{
return lhs.isbn() == rhs.isbn() &&
lhs.units_sold == rhs.units_sold &&
lhs.revenue == rhs.revenue;
}
bool
operator != (const Sales_data &lhs, const Sales_data &rhs)
{
return !(lhs == rhs); //通过 == 操作符来定义!=
}
9.赋值操作符
// = 操作符
StrVec&
StrVec::operator=(initializer_list<string> il)
{
// alloc_n_copy allocates space and copies elements from the given range
auto data = alloc_n_copy(il.begin(), il.end());
free(); // destroy the elements in this object and free the space
elements = data.first; // update data members to point to the new space
first_free = cap = data.second;
return *this;
}
// += 操作符
// member binary operator: left-hand operand is bound to the implicit this pointer
// assumes that both objects refer to the same book
Sales_data&
Sales_data::operator+=(const Sales_data &rhs)
{
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
10.下标操作符*
//类定义下标操作符时,一般需要定义两个版本:
//非const成员并返回引用;
//const成员并返回const引用;
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]; }
private:
std::string *elements; // pointer to the first element in the array
};
11.自增、自减操作符
//前缀自增自减,返回自身的引用
class StrBlobPtr {
public:
// increment and decrement
StrBlobPtr& operator++(); // prefix operators
StrBlobPtr& operator--();
// other members as before
};
// prefix: return a reference to the incremented/decremented object
StrBlobPtr&
StrBlobPtr::operator++()
{
// if curr already points past the end of the container, can't increment it
check(curr, "increment past end of StrBlobPtr");
++curr; // advance the current state
return *this;
}
StrBlobPtr&
StrBlobPtr::operator--()
{
// if curr is zero, decrementing it will yield an invalid subscript
--curr; // move the current state back one element
check(-1, "decrement past begin of StrBlobPtr");
return *this;
}
//后缀自增自减,先保存原值,自增后返回自增前的值,故不用引用;
//为区别前缀和后缀,后缀操作符函数接收一个无用的int型形参;
//在后缀操作符中,可以使用前缀操作符来实现自增自减;
class StrBlobPtr {
public:
// increment and decrement
StrBlobPtr operator++(int); // postfix operators
StrBlobPtr operator--(int);
// other members as before
};
// postfix: increment/decrement the object but return the unchanged value
StrBlobPtr
StrBlobPtr::operator++(int)
{
// no check needed here; the call to prefix increment will do the check
StrBlobPtr ret = *this; // save the current value
++*this; // advance one element; prefix ++ checks the increment
return ret; // return the saved state
}
StrBlobPtr
StrBlobPtr::operator--(int)
{
// no check needed here; the call to prefix decrement will do the check
StrBlobPtr ret = *this; // save the current value
--*this; // move backward one element; prefix -- checks the
decrement
return ret; // return the saved state
}
12.调用操作符和函数对象
struct absInt {
int operator()(int val) const {
return val < 0 ? -val : val;
}
};
//定义了调用操作符的类,其对象称为函数对象;
int i = -42;
absInt absObj; // object that has a function-call operator
int ui = absObj(i); // passes i to absObj.operator()
**标准库定义了一些函数对象,在functional头文件中定义;
13.转换与类类型
class SmallInt {
public:
SmallInt(int i = 0): val(i)
{
if (i < 0 || i > 255)
throw std::out_of_range("Bad SmallInt value");
}
//转换操作符,必须是成员函数,不能指定返回类型,形参表必须为空
//一般不应改变被转换的对象,所以为const;
operator int() const { return val; }
private:
std::size_t val;
};
//使用
Smallint si;
double dval;
if (si >= dval) //si转换为int,之后再转换为double
//...
cout << si <<endl; //si转换为int之后调用<<操作符
注意,只允许一次类类型转换:
比如可以Integral->SmallInt->int;但不能Integral->int;
14.给定以下代码:
ClassX sc;
int iobj = sc + 3;
有四种可能:
1.有一个重载加操作符与ClassX和int相匹配;
2.存在转换,则先进行类型转换,再进行加操作;
3.既定义了转换操作符又定义了+的重载版本,该表达式具有二义性;
4.既没有转换又没有重载+,该表达式非法。