运算符重载
Overloadable (可重载):
+ - * / % ^ & | ~ ! =
< > += -= *= /= %= ^= &= |= <<
>> >>= <<= == != <= >= && || ++ --
->* , -> [] () new delete
Operators That Cannot Be Overloaded (不可重载)
Operator Name
. 类属关系运算符
.* 成员指针运算符
:: 作用域运算符
? : 条件运算符
# 编译预处理符号
sizeof() 取数据类型的长度
运算符重载的限制:
①优先级和结合性不变
②不能创造新的运算符
1 #ifndef _RATIONAL_H_ 2 #define _RATIONAL_H_ 3 4 #include <string> 5 using namespace std; 6 7 class Rational 8 { 9 private: 10 long numerator_; 11 long denominator_; 12 static long gcd(long n,long d);//最大公约数 13 public: 14 Rational(); 15 Rational(long numerator, long denominator); 16 long getNumerator(); 17 long getDenominator(); 18 Rational add(Rational &secondRational); 19 Rational subtract(Rational &secondRational); 20 Rational multiply(Rational &secondRational); 21 Rational divide(Rational &secondRational); 22 int compareTo(Rational &secondRational); 23 bool equals(Rational &secondRational); 24 int intValue(); 25 double doubleValue(); 26 string toString(); 27 28 //Define function operators for relational operators 29 bool operator<(Rational &secondRational); 30 bool operator<=(Rational &secondRational); 31 bool operator>(Rational &secondRational); 32 bool operator>=(Rational &secondRational); 33 bool operator==(Rational &secondRational); 34 bool operator!=(Rational &secondRational); 35 36 //Define function operators for arithemetic operators 37 Rational operator+(Rational &secondRational); 38 Rational operator-(Rational &secondRational); 39 Rational operator*(Rational &secondRational); 40 Rational operator/(Rational &secondRational); 41 42 //Define function operators for shorthand operators 43 Rational operator+=(Rational &secondRational); 44 Rational operator-=(Rational &secondRational); 45 Rational operator*=(Rational &secondRational); 46 Rational operator/=(Rational &secondRational); 47 48 //Define function operator [] 49 long& operator[](const int &index); 50 51 //Define function operators for prefix ++ and -- 52 Rational operator++(); 53 Rational operator--(); 54 55 //Define function operators for postfix ++ and -- 56 Rational operator++(int dummy); 57 Rational operator--(int dummy); 58 59 //Define function operators for unary + and - 60 Rational operator+(); 61 Rational operator-(); 62 63 //Define the output and input operator 64 friend ostream &operator<<(ostream &stream, Rational &rational); 65 friend istream &operator>>(istream &stream, Rational &rational); 66 67 //Define function operator for conversion 68 operator double(); 69 }; 70 #endif
1 #include <iostream> 2 #include <sstream> 3 4 #include <cmath> 5 #include <cstdlib> 6 7 #include "rational.h" 8 using namespace std; 9 10 Rational::Rational() { 11 numerator_ = 0; 12 denominator_ = 1; 13 } 14 15 Rational::Rational(long numerator, long denominator) { 16 long factor = gcd(numerator, denominator); 17 numerator_ = ((denominator > 0) ? 1 : -1) * numerator / factor; 18 denominator_ = abs(denominator) / factor; 19 } 20 21 long Rational::gcd(long n,long d) { 22 long n1 = abs(n); 23 long n2 = abs(d); 24 int gcd = 1; 25 for(int i = 1; i <= n1 && i <= n2; i++) { 26 if(n1 % i == 0 && n2 % i == 0) 27 gcd = i; 28 } 29 return gcd; 30 } 31 32 long Rational::getNumerator() { 33 return numerator_; 34 } 35 long Rational::getDenominator() { 36 return denominator_; 37 } 38 39 Rational Rational::add(Rational &secondRational) { 40 long n = numerator_ * secondRational.getDenominator() + 41 denominator_ * secondRational.getNumerator(); 42 long d = denominator_ * secondRational.getDenominator(); 43 return Rational(n, d); 44 } 45 46 Rational Rational::subtract(Rational &secondRational) { 47 long n = numerator_ * secondRational.getDenominator() - 48 denominator_ * secondRational.getNumerator(); 49 long d = denominator_ * secondRational.getDenominator(); 50 return Rational(n, d); 51 } 52 53 Rational Rational::multiply(Rational &secondRational) { 54 long n = numerator_ * secondRational.getNumerator(); 55 long d = denominator_ * secondRational.getDenominator(); 56 return Rational(n, d); 57 } 58 59 Rational Rational::divide(Rational &secondRational) { 60 long n = numerator_ * secondRational.getDenominator(); 61 long d = denominator_ * secondRational.getNumerator(); 62 return Rational(n, d); 63 } 64 65 int Rational::compareTo(Rational &secondRational) { 66 Rational temp = this->subtract(secondRational); 67 if( temp.getNumerator() < 0) 68 return -1; 69 else if(temp.getNumerator() == 0) 70 return 0; 71 else 72 return 1; 73 } 74 bool Rational::equals(Rational &secondRational) { 75 if(this->compareTo(secondRational) == 0) 76 return true; 77 else 78 return false; 79 } 80 int Rational::intValue() { 81 return getNumerator() / getDenominator(); 82 } 83 84 double Rational::doubleValue() { 85 return 1.0 * getNumerator() / getDenominator(); 86 } 87 88 string Rational::toString() { 89 stringstream stringStream; 90 if( denominator_ != 1) { 91 stringStream << numerator_ << "/" << denominator_; 92 } else { 93 stringStream << numerator_; 94 } 95 return string( stringStream.str() ); 96 } 97 98 bool Rational::operator<(Rational &secondRational) { 99 return (this->compareTo(secondRational) < 0); 100 } 101 bool Rational::operator<=(Rational &secondRational) { 102 return (this->compareTo(secondRational) <= 0); 103 } 104 bool Rational::operator>(Rational &secondRational) { 105 return (this->compareTo(secondRational) > 0); 106 } 107 bool Rational::operator>=(Rational &secondRational) { 108 return (this->compareTo(secondRational) >= 0); 109 } 110 bool Rational::operator==(Rational &secondRational) { 111 return (this->compareTo(secondRational) == 0); 112 } 113 bool Rational::operator!=(Rational &secondRational) { 114 return (this->compareTo(secondRational) != 0); 115 } 116 Rational Rational::operator+(Rational &secondRational) { 117 long n = numerator_ * secondRational.getDenominator() + 118 denominator_ * secondRational.getNumerator(); 119 long d = denominator_ * secondRational.getDenominator(); 120 return Rational(n, d); 121 } 122 123 Rational Rational::operator-(Rational &secondRational) { 124 long n = numerator_ * secondRational.getDenominator() - 125 denominator_ * secondRational.getNumerator(); 126 long d = denominator_ * secondRational.getDenominator(); 127 return Rational(n, d); 128 } 129 Rational Rational::operator*(Rational &secondRational) { 130 long n = numerator_ * secondRational.getNumerator(); 131 long d = denominator_ * secondRational.getDenominator(); 132 return Rational(n, d); 133 } 134 Rational Rational::operator/(Rational &secondRational) { 135 long n = numerator_ * secondRational.getDenominator(); 136 long d = denominator_ * secondRational.getNumerator(); 137 return Rational(n, d); 138 } 139 140 Rational Rational::operator+=(Rational &secondRational) { 141 *this = this->add(secondRational); 142 return (*this); 143 } 144 Rational Rational::operator-=(Rational &secondRational) { 145 *this = this->subtract(secondRational); 146 return (*this); 147 } 148 Rational Rational::operator*=(Rational &secondRational) { 149 *this = this->multiply(secondRational); 150 return (*this); 151 } 152 Rational Rational::operator/=(Rational &secondRational) { 153 *this = this->divide(secondRational); 154 return (*this); 155 } 156 157 long& Rational::operator[](const int &index) { 158 if(index == 0) 159 return numerator_; 160 else if (index == 1) 161 return denominator_; 162 else { 163 cout << "subscript error" << endl; 164 exit(0); 165 } 166 } 167 168 //Define function operators for prefix ++ and -- 169 Rational Rational::operator++() { 170 numerator_ += denominator_; 171 return *this; 172 } 173 Rational Rational::operator--() { 174 numerator_ -= denominator_; 175 return *this; 176 } 177 178 //Define function operators for postfix ++ and -- 179 Rational Rational::operator++(int dummy) { 180 Rational temp(numerator_, denominator_); 181 numerator_ += denominator_; 182 return temp; 183 } 184 Rational Rational::operator--(int dummy) { 185 Rational temp(numerator_, denominator_); 186 numerator_ -= denominator_; 187 return temp; 188 } 189 190 //Define function operators for unary + and - 191 Rational Rational::operator+() { 192 numerator_ *= 1; 193 } 194 Rational Rational::operator-() { 195 numerator_ *= -1; 196 } 197 198 //Define the output and input operator 199 ostream &operator<<(ostream &stream, Rational &rational) { 200 stream << rational.numerator_ << " / " << rational.denominator_; 201 return stream; 202 } 203 istream &operator>>(istream &stream, Rational &rational) { 204 cout << "Enter numerator: "; 205 stream >> rational.numerator_; 206 cout << "Enter denominator: "; 207 stream >> rational[1]; 208 // stream >> rational.denominator_; 209 return stream; 210 } 211 212 //Define function operator for conversion 213 Rational::operator double() { 214 return doubleValue(); 215 }
1 #include <iostream> 2 #include "rational.h" 3 using namespace std; 4 5 int main() 6 { 7 Rational r1(4,2); 8 Rational r2(2,3); 9 10 // r1 = r1.add(r2); 11 12 cout << r1 << " > " << r2 << " is " << (r1 > r2) << endl; 13 cout << r1 << " < " << r2 << " is " << (r1 < r2) << endl; 14 cout << r1 << " == " << r2 << " is " << (r1 == r2) << endl; 15 cout << r1 << " != " << r2 << " is " << (r1 != r2) << endl; 16 17 cout << r1 << " + " << r2 << " = " << r1 + r2 << endl; 18 cout << r1 << " - " << r2 << " = " << r1-r2 << endl; 19 cout << r1 << " * " << r2 << " = " << r1*r2 << endl; 20 cout << r1 << " / " << r2 << " = " << r1/r2 << endl; 21 22 Rational r3(1,2); 23 r3 += r1; 24 cout << "r3 is " << r3 << endl; 25 26 Rational r4(1,2); 27 r4[0] = 3; 28 r4[1] = 4; 29 cout << "r4 is " << r4 << endl; 30 31 r3 = r4++; 32 cout << "r3 is " << r3 << endl; 33 cout << "r4 is " << r4 << endl; 34 35 cout << "1 + " << r4 << " is " << (1 + r4) << endl; 36 return 0; 37 }
定义一个有理数类
1 class Rational 2 { 3 private: 4 long numerator_; 5 long denominator_; 6 }
1.简单运算符重载
1 Rational Rational::operator+(Rational &secondRational) { 2 long n = numerator_ * secondRational.getDenominator() + 3 denominator_ * secondRational.getNumerator(); 4 long d = denominator_ * secondRational.getDenominator(); 5 return Rational(n, d); 6 }
2.重载[]运算符
[]重载后可用类似数组的语法格式访问对象内容
使[]返回一个引用,既可作为左值运算
来实现 数组下标运算符作为访问器和修改器:可读写
Rational r(2,3); int x = r[0]; r[1] = 5;
1 long& Rational::operator[](const int &index) { 2 if(index == 0) 3 return numerator_; 4 else if (index == 1) 5 return denominator_; 6 else { 7 cout << "subscript error" << endl; 8 exit(0); 9 } 10 }
3.重载一元运算符
--,++,-(负号)
当编译器遇到@obj; 时 (@代表单目运算符)
若operator @是在obj的类中的成员,则调用
obj.operator@()
若operator @是obj的类的friend 函数,则调用
operator @(obj)
前置重载无参数
后置重载带参数-- dummy(大米) -->只是用来区别两种自增算符,并不参加实际的运算。
1 //Define function operators for prefix ++ and -- 2 Rational Rational::operator++() { 3 numerator_ += denominator_; 4 return *this; 5 } 6 Rational Rational::operator--() { 7 numerator_ -= denominator_; 8 return *this; 9 } 10 11 //Define function operators for postfix ++ and -- 12 Rational Rational::operator++(int dummy) { 13 Rational temp(numerator_, denominator_); 14 numerator_ += denominator_; 15 return temp; 16 } 17 Rational Rational::operator--(int dummy) { 18 Rational temp(numerator_, denominator_); 19 numerator_ -= denominator_; 20 return temp; 21 } 22 23 //Define function operators for unary + and - 24 Rational Rational::operator+() { 25 numerator_ *= 1; 26 } 27 Rational Rational::operator-() { 28 numerator_ *= -1; 29 }
4.重载流提取/插入运算符
运算符重载为类成员函数后,当调用该运算符时,左操作数必须是该类的实例。若<<和>>重载为成员函数,则只能用r1<<cout
只能重载为友元函数
返回引用 可以 cout << r1 << r2;(从左到右)
无引用 只能 cout << r1;
其他重载也应注意返回值类型。
1 class Rational 2 { 3 friend ostream &operator<<(ostream &stream, Rational &rational); 4 friend istream &operator>>(istream &stream, Rational &rational); 5 }; 6 //Define the output and input operator 7 ostream &operator<<(ostream &stream, Rational &rational) { 8 stream << rational.numerator_ << " / " << rational.denominator_; 9 return stream; 10 } 11 istream &operator>>(istream &stream, Rational &rational) { 12 cout << "Enter numerator: "; 13 stream >> rational.numerator_; 14 cout << "Enter denominator: "; 15 stream >> rational[1]; 16 // stream >> rational.denominator_; 17 return stream; 18 }
5.对象转换运算符
1 double Rational::doubleValue() { 2 return 1.0 * getNumerator() / getDenominator(); 3 } 4 5 Rational::operator double(){ 6 returndoubleValue(); 7 } 8 Eg: 9 Rational r1(1,4); 10 double d = r1 +5.1; 11 cout <<"r1 + 5.1 is "<<d <<endl;
6.重载赋值运算符
默认情况下,赋值运算符执行对象成员的一对一拷贝
重载赋值运算符,改变其默认工作方式(浅拷贝 深拷贝)
赋值运算符 永远返回一个 *this的引用
Eg:
MyClass& MyClass::operator=(const MyClass& myclass) {
//code
return *this;
}
使得 MyClass a,b,c;
a=b=c;合法
7.关于const 和引用&
const:如果类的成员函数不会改变对象的状态,那么这个成员函数应被声明为常函数。
返回 引用& 或 类:取决于你所希望得到的结果。Eg:连等 a = b = c