重載前須知
- 如果類執行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是指針,則應該使用內置的箭頭運算符,表達式等價於上面的第一條。