1.运算符重载的本质就是类对象调用一个运算符重载函数。比如说重载“+”运算符,其实是在调用operator+()这个函数。为支持多种运算,一个运算符可能有好几个同名的运算符重载函数,此时C++编译器会根据调用对象的类型决定调用哪个重载函数。例如在实现加法运算(+)时,C++编译器会根据+号左右两侧的元素类型,决定调用哪个重载函数。
例如:
1 //.h文件 2 #pragma once 3 class Complex 4 { 5 public: 6 Complex(int A=0,int B=0); 7 ~Complex(void); 8 Complex operator+(Complex&); 9 Complex operator+(int&); 10 void printC(void); 11 12 private: 13 int a; 14 int b; 15 }; 16 17 18 //.cpp文件 19 #include "Complex.h" 20 #include<iostream> 21 22 23 Complex::Complex(int A,int B) 24 { 25 a=A; 26 b=B; 27 } 28 29 30 Complex::~Complex(void) 31 { 32 } 33 34 Complex Complex::operator+(Complex& temp) 35 { 36 Complex c(this->a+temp.a,this->b+temp.b); 37 return c; 38 } 39 40 Complex Complex::operator+(int& temp) 41 { 42 Complex c(this->a+temp,this->b); 43 return c; 44 } 45 46 void Complex::printC(void) 47 { 48 std::cout<<a<<"+"<<b<<"i"<<std::endl; 49 } 50 51 52 //main函数 53 #include<iostream> 54 #include "Complex.h" 55 56 using namespace std; 57 58 59 60 int main() 61 { 62 int i=5; 63 Complex c1(1,2),c2(3,4); 64 65 Complex c3=c1+c2; 66 c3.printC(); 67 68 Complex c4=c1+i; 69 c4.printC(); 70 71 72 system("pause"); 73 return 0; 74 }
2.C++中的重载运算符如果访问的是类的私有属性,除了把重载运算符函数写在类的里面作为成员函数,还可以将重载运算符函数写在类的外面,但此时重载运算符函数要被声明为友元函数,否则将无法访问类的私有属性。例如对上面的重载"+"运算符,如果将重载运算符函数写在类体的外面,可以写成:
friend Complex operator+(Complex& c1,Complex& c2);//在类体里面声明重载运算符函数为由原函数
//重载运算符函数在类体外的实现
Complex operator+(Complex& c1,Complex& c2)
{
Complex c(c1.a+c2.a , c1.b+c2.b);
return c;
}
3.C++重载单目运算符,如"--"运算符时,由于"--"运算符有两种用法:--a(前置) 和 a++(后置) 所以重载"--"运算符时,写重载函数的时候就需要注意了,必须使重载函数的函数输入参数有所区别。可是"--"运算符写在类里面时,无须输入函数参数,为了区别前置"--"和后置"--"的重载函数,这时候我们就需要使用占位符了。
例如:
1 //.h文件 2 #pragma once 3 class Complex 4 { 5 public: 6 Complex(int A=0,int B=0); 7 ~Complex(void); 8 Complex operator+(Complex&); 9 Complex operator+(int&); 10 //friend Complex operator+(Complex& c1,Complex& c2); 11 12 Complex& operator--(void);//前置-- 13 Complex operator--(int);//后置-- ,int是占位符 14 void printC(void); 15 16 private: 17 int a; 18 int b; 19 }; 20 21 22 //.cpp文件 23 #include "Complex.h" 24 #include<iostream> 25 26 27 Complex::Complex(int A,int B) 28 { 29 a=A; 30 b=B; 31 } 32 33 34 Complex::~Complex(void) 35 { 36 } 37 38 //********************************************重载"+"运算符**************************************** 39 Complex Complex::operator+(Complex& temp) 40 { 41 Complex c(this->a+temp.a,this->b+temp.b); 42 return c; 43 } 44 45 Complex Complex::operator+(int& temp) 46 { 47 Complex c(this->a+temp,this->b); 48 return c; 49 } 50 51 52 /* 53 Complex operator+(Complex& c1,Complex& c2) 54 { 55 Complex c(c1.a+c2.a,c1.b+c2.b); 56 return c; 57 } 58 */ 59 60 61 62 //********************************************重载"--"运算符**************************************** 63 //前置-- 64 Complex& Complex::operator--() 65 { 66 this->a--; 67 this->b--; 68 69 return *this;//返回的是一个引用,即this指针指向的对象本身 70 } 71 72 73 //后置-- 74 Complex Complex::operator--(int) 75 { 76 Complex temp=*this; 77 78 this->a--; 79 this->b--; 80 81 return temp; 82 } 83 84 85 void Complex::printC(void) 86 { 87 std::cout<<a<<"+"<<b<<"i"<<std::endl; 88 } 89 90 91 //main函数 92 #include<iostream> 93 #include "Complex.h" 94 95 using namespace std; 96 97 98 99 int main() 100 { 101 int i=5; 102 Complex c1(1,2),c2(3,4); 103 104 105 --c2; 106 c2.printC(); //输出2+3i 107 108 Complex c3=c2--; 109 c2.printC(); //输出1+2i 110 c3.printC(); //输出2+3i 111 112 system("pause"); 113 return 0; 114 }
4.C++重载"<<"运算符:
"<<"运算符的本质是ostream类的对象cout重载的一个函数,我们无法在ostream类里面将"<<"的重载函数添加为类ostream的成员函数,也无法在ostream类里面将"<<"的重载函数声明为ostream类的友元函数,因为我们根本无法得到ostream类的原码。所以只能在Complex类里面将"<<"的重载函数添加为类Complex的成员函数,或者将"<<"的重载函数声明为Complex类的友元函数。如果将"<<"运算符的重载函数写成是类Complex的成员函数,则调用的时候也是不对的。因为"<<"运算符是左结合的,它的重载函数本质上是ostream& operator<<(Complex&)的形式,如果写成类的成员函数形式只能是写在ostream类里面,肯定由cout这个对象来调用,即cout.operator<<(Complex对象)的调用形式,不可能是写在Complex类里面由Complex的类对象来调用(左结合性)。而我们前面提到过,我们无法得到ostream类的源码,无法将重载函数写在sstream类里面,因此,我们做出结论:”<<“运算符重载函数只能是声明为Complex类的友元函数。具体代码如下:
friend ostream& operator<<(ostream&,Complex&);//在Complex类体里面将operator<<函数声明为类Complex的由原函数
//operator<<友元函数的实现代码
ostream& operator<<(ostream& out,Complex& c)
{
out<<c.a<<"+"<<c.b<<"i";
return out;
}
//上面的代码中之所以返回ostream&是为了<<可以串联使用。如cout<<c1<<"Hello"<<endl
当被重载的运算符的左右两侧的操作数类型不一样的时候,最好用友元函数重载运算符,这样无论哪种类型的操作数写在前面,都能调用运算符重载函数。
5.C++里面不能重载的运算符有5个:
.(成员访问运算符)
.*(成员指针访问运算符)
::(域运算符)
sizeof(长度运算符)
?:(条件运算符)
6.C++里面最好不要重载"&&"和"||"运算符,虽然在语法上它们支持重载,但重载的运算符无法实现原来运算符的短路效果。所谓的短路效果是指:a&&b,若果a表达式是假,则不必判断b表达式,直接判断(a&&b)为假。而重载“&&”运算符后,调用重载后的"&&"运算符本质上是执行a.operator&&(b)函数,它一定是先执行b表达式的,所以无法实现短路效果