转自: benben
重载操作符是个好青年,但是要吐槽的是,我们时常为了重载操作符编写许多重复的代码。这是枯燥的,但是也是必须的。你重载的越多,你的类的弹性就越大。但是,你也不能为所欲为。玩游戏总是遵守相应的规则,写重载操作符亦是如此!
以下是要遵守的游戏规则:
在看完游戏规则之后,我们就各个部分的实现和注意点进行肢解。
⒈ 输入和输出操作符的重载
对于>>和<<的重载要注意以下几个要点:
① IO操作符必须为非成员函数,如果将其定义为成员函数,那么IO操作符的操作习惯将和正常的习惯相反。多怪啊!此时,你或许会问,那我怎么调用对象中的私有成员呢?别急,我们不是有友员和友类吗?将IO操作符重载函数定义成类的友员函数,这个问题就迎刃而解了。
② 在输入期间,我们可能会碰到错误。此时,要恢复对象为初始状态。也就是,在输入之前什么样子,我们就恢复成那个样子。
③ 这个要点是摘至《C++ primer》,我觉得挺好的。我们可以重载操作符,意味着我们自由的空间就大了。但是,我们不要忘了IO操作符的本质,不要过度的格式化,应将格式化降到最低。
在注意了几个要点之后,我们看一个完整的IO操作符的实现例子:
#include #include using namespace std; class MyClass { private: string name; int id; int prefix; int value; public: MyClass() { }; MyClass(string n, int a, int p, int nm):name(n), id(a), prefix(p), value(nm){} // 利用初始化列表来初始化成员对象 friend ostream &operator<<(ostream &stream, MyClass o); // 操作符被定义为非成员函数时,要将其定义为所操作类的友员 friend istream &operator>>(istream &stream, MyClass &o); }; ostream &operator<<(ostream &stream, MyClass o) { stream << o.name << " "; stream << "(" << o.id << ") "; stream << o.prefix << "-" << o.value << "\n"; return stream; } istream &operator>>(istream &stream, MyClass &o) { cout << "Enter name: "; stream >> o.name; cout << "Enter id: "; stream >> o.id; cout << "Enter prefix: "; stream >> o.prefix; cout << "Enter value: "; stream >> o.value; cout << endl; return stream; } int main() { MyClass a; operator>>(cin, a); // 相当于operator>>(cin, a) cout << a; // 相当于operator<<(cout, a) return 0; }
我觉得,许多的事情都是尽在不言中。看了代码,你就知道,这个家伙是这么用的,这样用才是规范的。好了接下来介绍算术操作符和关系操作符。
⒉ 算术操作符和关系操作符的重载
一般而言,将算术操作符和关系操作符定义为非成员函数。
① 算术操作符
那就看代码怎么实现吧:
#include #include using namespace std; class Point { public: Point(){}; Point(int x_, int y_):x(x_),y(y_){}; Point(const Point &p){ this->x = p.x; this->y = p.y; }; ~Point(){}; friend Point operator+(Point &p1, Point &p2); // 两个对象相加 friend Point operator+(int value, Point &p1); // 对象和值的相加 friend ostream &operator<<(ostream &os, Point &p1); private: int x; int y; }; Point operator+(Point &p1, Point &p2) { Point temp; temp.x = p1.x + p2.x; temp.y = p1.y + p2.y; return temp; } Point operator+(int value, Point &p1) { Point temp; temp.x = p1.x + value; temp.y = p1.y + value; return temp; } ostream &operator<<(ostream &os, Point &p1) { os << p1.x << " " << p1.y << endl; return os; } int main() { Point p1(1,2); Point p2(3,4); cout << p1 + p2; cout << 5 + p1; return 0; }
② 相等操作符
首先,“==”相等操作符的两个对象包含相同的数据,这样才有比较性。其次,定义了operator==,同时也要定义operator!=。
friend bool operator==(Point &p1, Point &p2); friend bool operator!=(Point &p1, Point &p2); ....... bool operator==(Point &p1, Point &p2) { return (p1.x == p2.x)&&(p1.y == p2.y); } bool operator!=(Point &p1, Point &p2) { return(p1.x !== p2.x)||(p1.y != p2.y); }