重载前须知
- 如果类执行IO操作,则定义移位运算符使其与内置类的IO 一致。
- 一般定义了相等性运算符==,那么也应该定义!= 运算符。
- 一个类定义了一个比较运算符,那么它也应该定义其他比较运算符。
- 重载运算符的返回类型应该和内置版本的返回类型一致。
- 赋值(=)、 下标([])、调用(())和成员访问箭头运算符必须定义为成员函数
- 复合赋值运算符一般定义为成员函数,但不是必须的
- 改变对象状态的运算符或者与给定类型密切相关的运算符,如递增、递减和解引用运算符,一般定义为成员函数
- 具有对称性的运算符可能转换任意一端的运算对象,例如算术、相等性、关系和位运算符等,通常应该为非成员函数。
输入和输出运算符
重载输出运算符
Sales_data的输出运算符:
ostream& operator << (ostream& os, const Sales_data& item) {
os << item.isbn() << " " << item.units_sold << " " <<item.revenue << " " << item.avg_price();
return os;
}
重载输入运算符
Sales_data的输入操作:
istream& operator >> (istream& is, Sales_data& item) {
double price;
is >> item.bookNo >> item.units_sold >> price;
if (is) // 检测输入流
item.revenue = item.units_sold * price;
else
item = Sales_data(); // 输入失败,对象被赋予默认状态
return is;
}
算术和关系运算符
算术运算符
Sales_data operator + (const Sales_data& lhs, const Sales_data& rhs) {
Sales_data sum = lhs;
sum += rhs;
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);
}
关系运算符
赋值运算符
StrVec& StrVec::operator = (initializer_list<string> il) {
auto data = alloc_n_copy(il.begin(), il.end());
free();
first = data.first;
last_end = cap = data.last_end;
return *this;
}
赋值运算符应该先释放左则对象的内存空间。
Sales_data& Sales_data::operator += (const Sales_data& rhs) {
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
下标运算符
class StrVec {
public:
std::string& operator [] (size_t n) { return first[n]; }
const std::string& operator [] (size_t n) const { return first[n]; }
private:
std::string* first; // 指向数组的首元素
};
递增和递减运算符
class StrBlobPtr {
public:
StrBlobPtr& operator++();
StrBlobPtr& operator--();
//
};
前置版本的递增/递减运算符应该返回递增或递减后的对象的引用。
class StrBlobPtr {
public:
StrBlobPtr operator++(int);
StrBlobPtr operator--(int);
//
};
为了前置版本和后置版本,将后置版本中的参数列表中添加一个int型参数,但是这个int型只是用来区分前置和后置版本的运算符,并不使用它。
成员访问运算符
class StrBlobPtr {
public:
std::string& operator*() const {
auto p = check(curr, "dreference past end");
return (*p)[curr];
}
std::string* operator->()const {
return & this->operator*();
}
//
};
(*point).mem; // (1)
point.operator()->mem; // (2)
如果point是指针,则应该使用内置的箭头运算符,表达式等价于上面的第一条。