1、通过连接其他合法符号可以创建新的操作符。
2、除了函数调用操作符operator()之外,重载操作符时使用默认实参是非法的。
3、重载操作符的形参数目(包括成员函数的隐式this指针)与操作符的操作数数目相同,函数调用操作符可以接受任意数目的操作数。
4、作为类成员的重载函数,其形参看起来比操作数数目少1.作为成员函数的操作符有一个隐含的this形参,限定为第一个操作数。
5、如果不定义,编译器将会合成的操作符有:赋值操作符(=)、取地址操作符(&)、逗号操作符(,)、&&和||。重载之后的&&和||不再具有短路特征。
6、选择成员或非成员实现的几点经验原则:
l 赋值(=)、下标([])、调用(())和成员访问箭头(->)等操作符必须定义为成员,将这些操作符定义为非成员函数将在编译时标记为错误。
l 像赋值一样,复合赋值操作符通常应定义为类的成员。与赋值不同的是,不一定非得这样做,如果定义非成员符合赋值操作符,不会出现编译错误。
l 改变对象状态或与给定类型紧联系的其他一些操作符,如自增、自减和解引用,通常应定义为类成员。
l 对称的操作符,如算术操作符、相等操作符、关系操作符和位操作符,最好定义为普通非成员函数。
7、不能滥用转换函数,应该只有一个内置类型的转换
下面是自己写的实现:
#ifndef INT_H #define INT_H #include <iostream> using namespace std; class INT { public: //因为定义了转换操作符,如果不禁止接受int形参的构造函数隐式转换的话, //将产生重定义的效果,例如表达式 INT i; i + 1.0f; //这样将不知道是将1.0f转换为1再调用构造函数,还是将i转换为float类型 explicit INT(int i = 0); //下面的函数由编译器产生的已经可以达到我们的目标,故不定义 //INT(const& INT); //~INT(); //为了与IO标准库一致,操作符应接受ostream&作为 //第一个形参,对类型const对象的引用作为第二个形参, //并返回对ostream形参的引用,而且必须为非成员函数 //因为会访问到类的私有成员函数,所以声明为友元 friend ostream& operator<<(ostream& out , const INT& r); //输入操作符的第一个形参是一个引用,指向它要读的流,并且返回的为同一个流的引用。 //与输出操作符不同的是,第二个形参为非const引用(当然,输出操作符也不一定是const的引用) //那是因为输入操作符的目的是将数据读到这个对象中 //!输入操作符必须处理错误和文件结束的可能性(这里为简单起见,则不处理) friend istream& operator>>(istream& in, INT& r); //复合赋值操作符 INT& operator+=(const INT& r); INT& operator-=(const INT& r); INT& operator*=(const INT& r); INT& operator/=(const INT& r); /*按照经验原则,一般把对称的操作符定义为非成员函数*/ //直接用复合赋值操作符来实现算术操作符,可以不必创建和撤销一个临时变量来保存结果(还没理解, //不知道怎么样的实现才可以不用这一步) //算术操作符可以不是友元函数,如果用符合赋值操作符实现的话 friend INT operator+(const INT& l, const INT& r); friend INT operator-(const INT& l, const INT& r); friend INT operator*(const INT& l, const INT& r); friend INT operator/(const INT& l, const INT& r); /*按照经验原则,一般把对称的操作符定义为非成员函数*/ friend bool operator==(const INT& l, const INT& r); friend bool operator!=(const INT& l, const INT& r); friend bool operator<(const INT& l, const INT& r); friend bool operator<=(const INT& l, const INT& r); friend bool operator>(const INT& l, const INT& r); friend bool operator>=(const INT& l, const INT& r); //赋值操作符,如果不定义一个赋值操作符,编译器将会合成一个, //所以必须定义为成员函数,参数一般为类类型的const引用 INT& operator=(const INT&); INT& operator=(int); //转换操作符 //转换函数通用形式为operator type(); //转换函数必须是成员函数,不能指定返回类型,但是必须显示返回一个指定类型的值, //并且形参表为空(象征性的定义了float型的,其他的类似) operator float() const { return static_cast<float>(_value); } //构造函数接受了一个int的构造函数,故不应该定义int的转换函数 //operator int() const { return _value; } /*按照经验原则,一般把改变对象状态的操作符定义为类成员*/ //为了与内置类型一致,前缀式操作符应返回对象的引用 INT& operator++(); //prefix operators INT& operator--(); //prefix operators //为了区分是后缀式还是前缀式,给后缀式加一个int参数,int参数只是起区分作用 //后缀式可以用前缀式来实现,且返回值一般为值 INT operator++(int); //postfix INT operator--(int); //postfix private: int _value; }; #endif
#include "INT.h" #include <iostream> std::ostream& operator <<(std::ostream &out, const INT &r) { out << r._value; return out; } istream& operator >>(istream& in, INT& r) { in >> r._value; return in; } INT operator+(const INT& l, const INT& r) { INT ret(l); ret += r; return ret; } INT operator-(const INT& l, const INT& r) { INT ret(l); ret -= r; return ret; } INT operator*(const INT& l, const INT& r) { INT ret(l); ret *= r; return ret; } INT operator/(const INT& l, const INT& r) { INT ret(l); ret /= r; return ret; } bool operator==(const INT& l, const INT& r) { return l._value == r._value; } bool operator!=(const INT& l, const INT& r) { return !(l == r); } bool operator<(const INT& l, const INT& r) { return l._value < r._value; } bool operator<=(const INT& l, const INT& r) { return (l < r) || (l == r); } bool operator>(const INT& l, const INT& r) { return !(l <= r); } bool operator>=(const INT& l, const INT& r) { return !(l < r); } ////////////////////////////////////////////////////////////// INT::INT(int i) { _value = i; } INT& INT::operator =(const INT & r) { _value = r._value; return *this; } INT& INT::operator =(int r) { _value = r; return *this; } INT& INT::operator +=(const INT &r) { _value += r._value; return *this; } INT& INT::operator -=(const INT &r) { _value -= r._value; return *this; } INT& INT::operator /=(const INT &r) { _value /= r._value; return *this; } INT& INT::operator *=(const INT &r) { _value *= r._value; return *this; } INT& INT::operator ++() { ++ _value; return *this; } INT& INT::operator --() { -- _value; return *this; } INT INT::operator ++(int) { INT ret(*this); ++*this; return ret; } INT INT::operator --(int) { INT ret(*this); --*this; return ret; }