概念 C++中运算符可以通过下面的方式重载,从而为自定义类型定义运算。
可以重载的运算符包括
算术运算符(+、-、*、/)
关系运算符(==、!=、<、>)
赋值运算符(=)
插入流和提取流运算符(<<、>>)
等。
运算符重载实例 1. 算术运算符(+、-、*、/) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 #include <iostream> using namespace std;class Complex {private : double real; double imag;public : Complex (double r = 0.0 , double i = 0.0 ) : real (r), imag (i) {} Complex operator +(const Complex& other) { return Complex (real + other.real, imag + other.imag); } Complex operator -(const Complex& other) { return Complex (real - other.real, imag - other.imag); } void display () { cout << real << " + " << imag << "i" << endl; } };int main () { Complex c1 (3.0 , 4.0 ) ; Complex c2 (1.0 , 2.0 ) ; Complex c3 = c1 + c2; c3. display (); Complex c4 = c1 - c2; c4. display (); return 0 ; }
算符运算符重载的返回值是同类型的对象
因为算术运算符本身就不修改操作符,返回同类型的对象符合语义
算术运算符本身就要在操作符函数内产生新的对象,这个对象的作用域局限在函数内部,如果返回引用的话,这个引用所绑定的对象在函数结束后会被释放,返回引用会出现段错误1 2 3 Complex& operator +(const Complex& other) const { return Complex (real + other.real, imag + other.imag); }
如果返回引用,就不能向上面这样写了,因为这样写的返回值是一个不具名的右值 ,不能绑定到左值引用。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 #include <iostream> class Complex {private : double real; double imag;public : Complex (int r, int i):real (r),imag (i) { std::cout << "Complex(int, int) constructor called" << std::endl; } Complex& operator +(const Complex& other) const { Complex result (real + other.real, imag + other.imag) ; return result; } void print () const { std::cout << real << " + " << imag << "i" << std::endl; } ~Complex () { std::cout << "Complex destructor called" << std::endl; } };int main () { Complex num1 (3 , 4 ) ; Complex num2 (1 , 2 ) ; Complex result = num1 + num2; std::cout << "num1 = :" ; num1. print (); std::cout << "num2 = :" ; num2. print (); std::cout << "num1 + num2 = :" ; result.print (); return 0 ; }
上代码的输出是1 2 3 4 Complex(int, int) constructor called Complex(int, int) constructor called Complex(int, int) constructor called Complex destructor called
并且在运行到Complex result = num1 + num2;出现了段错误Segmentation fault,说明result在函数结束时就已经析构,因此Complex&找不到要绑定的对象。
2. 关系运算符(==、!=、<、>) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 #include <iostream> using namespace std;class Complex {private : double real; double imag;public : Complex (double r = 0.0 , double i = 0.0 ) : real (r), imag (i) {} bool operator ==(const Complex& other) { return (real == other.real) && (imag == other.imag); } bool operator !=(const Complex& other) { return !(*this == other); } void display () { cout << real << " + " << imag << "i" << endl; } };int main () { Complex c1 (3.0 , 4.0 ) ; Complex c2 (3.0 , 4.0 ) ; Complex c3 (1.0 , 2.0 ) ; if (c1 == c2) { cout << "c1 and c2 are equal." << endl; } else { cout << "c1 and c2 are not equal." << endl; } if (c1 != c3) { cout << "c1 and c3 are not equal." << endl; } else { cout << "c1 and c3 are equal." << endl; } return 0 ; }
3. 赋值运算符(=) 需要注意的是
返回值应该是对象的引用
允许进行连续赋值 obj3 = obj2 = obj1
防止返回对象时调用拷贝构造函数和析构函数,造成不必要的开销
需要注意自赋值问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 #include <iostream> #include <cstring> using namespace std;class MyString {private : char * str;public : MyString (const char * s = "" ) { str = new char [strlen (s) + 1 ]; strcpy (str, s); } ~MyString () { delete [] str; } MyString& operator =(const MyString& other) { if (this == &other) { return *this ; } delete [] str; str = new char [strlen (other.str) + 1 ]; strcpy (str, other.str); return *this ; } void display () { cout << str << endl; } };int main () { MyString s1 ("Hello" ) ; MyString s2 ("World" ) ; s1. display (); s2. display (); s2 = s1; s2. display (); return 0 ; }
4. 插入流和提取流运算符(<<、>>) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 #include <iostream> using namespace std;class Complex {private : double real; double imag;public : Complex (double r = 0.0 , double i = 0.0 ) : real (r), imag (i) {} friend ostream& operator <<(ostream& os, const Complex& c); }; ostream& operator <<(ostream& os, const Complex& c) { os << c.real << " + " << c.imag << "i" ; return os; }int main () { Complex c; cout << c << endl; return 0 ; }
注意事项
以下的运算符不能重载
成员访问运算符 .
成员指针访问 .*
作用域解析运算符 ::
条件运算符 ?:
sizeof运算符
运算符重载不能改变运算符的优先级和结合性
基本数据类型的运算符不能重载,如果运算符有2个及以上操作数,则至少一个操作数是自定义类型