1. 程式人生 > >C++第4章 (運算子的過載)

C++第4章 (運算子的過載)

一,過載方法

運算子的過載實質是函式的過載

雙目運算子 過載為友元,單目運算子過載為 成員函式

一般格式

函式型別 operator運算子名稱(形參表)

{ 對運算子的過載處理 }

operator是關鍵字

例過載 + 號

#include <iostream>
using namespace std;

class Complex{
	public:
		Complex();
		Complex(double, double);
		Complex operator+(Complex &);
		void display();
	private:
		double real;
		double imag;
};
Complex::Complex(){
	real = 0;
	imag = 0;
}
Complex :: Complex(double r, double i){
	real = r;
	imag = i;
} 
Complex Complex::operator+(Complex &c2)
{
	Complex c; 
	c.real = real + c2.real;
	c.imag = imag + c2.imag;
	return c;
}

void Complex::display(){
	cout << "( " << real << " , " << imag << " )" << endl; 
}
int main (){
	Complex c1(3, 4), c2(5, -10), c3;
	c3 = c1 + c2;
	cout << "c1 = "; c1.display();
	cout << "c2 = "; c2.display();
	cout << "c1 + c2 = "; c3.display();
	return 0;
} 

簡單寫法

Complex Complex :: operator+(Complex &c2){
	return Complex(real + c2.real, imag + c2.imag);	
}

相當於

c1.operator + (c2);

如果寫為

c3 = 3 + c2;	//錯誤 
c3 = Complex(3, 0) + c2;	//正確 

二,運算子過載規則

(1)C++不語序使用者自己定義新的運算子,只能對已有的C++運算子進行過載

(2)不能過載的運算子只有 5 個

 

. (成員訪問運算子)
* (成員指標訪問運算子)
:: (域運算子)
sizeof (長度運算子)
?:

(條件運算子)

(3)過載不能改變運算子運算物件(即運算元)的個數(雙目運算子 單目運算子)

(4)過載不能改變運算子的優先級別。

(5)過載不能改變運算子的結合性(如 = 的左右)

(6)過載運算子的函式不能有預設的引數。

(7)過載運算子必須和使用者定義的定義型別物件一起使用,其引數至少應該有一個是類物件。

int operator+(int a, int b){
	return (a - b);     //錯誤
} 
        //實際上是可以的  但是 這樣不遵守規則

但是可以寫複數和常數相加

Complex Complex :: operator+(double a){        //成員函式,類內宣告類外定於
	return Complex(real + a, imag);	
}

Complex :: operator+(double a, Complex &c2){    //只能為友元函式
	return Complex(c2.real + a, c2.imag);	
}

(8)= 和 & 不用過載

(9)> 可以過載為 小於 但是  這樣違背了運算子過載的初衷,並且容易混淆

三,運算過載函式作為類成員和友元函式

兩種處理方式

(1)把運算過載函式作為類的成員函式

(2)運算子過載函式可以不是類的成員函式(普通函式),在類中把它宣告為友元函式。

class Complex{
	public:
		Complex();
		Complex(double, double);
		friend Complex operator+(Complex &, Complex &);
		void display();
	private:
		double real;
		double imag;
};
Complex operator+(Complex &c1, Complex &c2)
{
	Complex c
	c.real = c1.real + c2.real;
	c.imag = c1.imag + c2.imag;
	return c;
}

相當於

operator + ( c1, c2 );

class Complex{
	public:
		Complex();
		Complex(double, double);
		friend Complex operator + (Complex &, Complex &);
		friend Complex operator + (Complex &, double);
		friend Complex operator + (double , Complex &);
		void display();
	private:
		double real;
		double imag;
};
Complex::Complex(){
	real = 0;
	imag = 0;
}
Complex :: Complex(double r, double i){
	real = r;
	imag = i;
} 
Complex operator + (Complex &c1, Complex &c2)
{
	Complex c;
	c.real = c1.real + c2.real;
	c.imag = c1.imag + c2.imag;
	return c1;
}
Complex operator + (Complex &c1, double a){
	return Complex(c1.real + a, c1.imag);
}
Complex operator + (double a, Complex &c1){
	return Complex(c1.real + a, c1.imag);
}

(1)C++規定,賦值運算子=, 下標運算子 [ ],函式呼叫運算子 (),成員運算子 ->,必須作為成員函式

(2)插入流 << 和提取運算子 >> ,型別轉換運算子不能定義為類的成員函式。只能作為友元函式。

(3)一般將單目運算子和符合運算子(+= ,-= ,/=,*=,&=,!=,'=,%=,%=,>>=,<<=)過載為成員運算子

(4)一般雙目運算子過載為友元函式

四,過載雙目運算子

 == < >

#include<iostream>
#include<cstring>

using namespace std;

class String {
	public :
		String (){ p = NULL; }
		String (char *str);
		friend bool operator > (String &, String &);
		friend bool operator < (String &, String &);
		friend bool operator == (String &, String &);
		void display();
	private :
		char *p;
};

String :: String (char *str){
	p = str;
}

void String :: display(){
	cout << p;
}

bool operator > (String &str1, String &str2){
	if(strcmp ( str1.p, str2.p ) > 0)
		return true;
	else
		return false;
}
bool operator < (String &str1, String &str2){
	if(strcmp ( str1.p, str2.p ) < 0)
		return true;
	else
		return false;
}
bool operator == (String &str1, String &str2){
	if(strcmp ( str1.p, str2.p ) == 0)
		return true;
	else 
		return false;
}

void compare (String &str1, String &str2){
	if(str1 > str2){
		str1.display();
		cout << " > " ;
		str2.display(); 
	}
	else if(str1 < str2){
		str1.display();
		cout << " < " ;
		str2.display(); 
	}
	else
	{
		str1.display();
		cout << " = " ;
		str2.display(); 
	 } 
	
}
int main (){
	String str1("Hello"), str2("the word"), str3("Computer");
	String str4("What!");
	compare(str1, str2); 
	return 0;
} 

五,過載單目運算子

++  -- +=

++i  和 i++

#include<iostream>
using namespace std;
class Time{
	public :
		Time () ;
		Time (int , int) ;
		Time operator++();    //前置:++ 運算子 ++i
		Time operator++(int);    //後置 ++ 運算子    i++
		void display();
	private :
		int minute;
		int sec;
};
Time::Time(){
	minute = 0;
	sec = 0;
}
Time :: Time (int m, int s){
	minute = m;
	sec = s;
}
Time Time:: operator ++ (){
	if(++sec >= 60){
		sec -= 60;
		++minute;
	}
	return *this;
}
Time Time::operator ++(int){
	Time temp(*this);
	sec ++;
	if(sec >= 60){
		sec -= 60;
		++minute;
	}
	return temp;
}
void Time::display(){
	cout << minute << ": " << sec << endl;
}
int main()
{
	Time t1(30, 59);
	t1 ++;
	t1.display();
	Time t2 ;
	t2 = t1 ++;
	t2.display();
	t1.display(); 
	return 0;
}

六,過載輸入流和輸出流  <<  >>

istream & operator >> ( istream &, 自定義類 &)

ostream & operator << ( ostream &, 自定義類 & )

<<有兩個引數,一個是輸出流物件(我們常用的cout),還有就是要輸出的東西。
例如:cout<<"haha";
也就是說<<的第一個引數必須是輸出流物件。
在成員函式裡實現<<過載,我們知道this會作為第一個引數,而這是不符合要求的。
>>類似!

所以我們過載 " >> " 和 " << " 的函式只能作為友元函式,而不能將它們定義為成員函式。

#include <iostream>
using namespace std;
class Complex{
	public :
		Complex ();
		Complex (double ,double);
		Complex operator +(Complex &);
		friend ostream &operator << (ostream &, Complex &);
	private :
		double real;
		double imag;
};
Complex:: Complex(){
	real = 0;
	imag = 0;
}
Complex :: Complex (double r, double i){
	real = r;
	imag = i;
}
Complex Complex::operator +(Complex &c2){
	return Complex (real + c2.real, imag + c2.imag);
}
ostream &operator <<(ostream &cout, Complex &c){
	cout << "( " << c.real << " , " << c.imag << " )" << endl; 
	return cout;
}


int main (){
	Complex c1(2, 4), c2 (3, 6), c3;
	c3 = c1 + c2;
	cout << c3 ;
	return 0;
} 

operator << ( cout , c3 );

#include<iostream>
using namespace std;
class Complex{
	public :
		friend ostream& operator <<(ostream &, Complex &);
		friend istream& operator >>(istream &, Complex &);
	private :
		double real;
		double imag;
};
ostream &operator << (ostream &cout, Complex &c){
	cout << "( " << c.real << " ";
	if(c.imag >= 0)
	cout << "+";
	cout << " " << c.imag << "i )" << endl;
	return cout;
}
istream &operator >> (istream &cin, Complex &c){
	cout << "Please cin the real and imag : "; 
	cin >> c.real >> c.imag;
	return cin;
}
int main(){
	Complex c1, c2;
	cin >> c1 >> c2;
	cout << c1 << c2;
	return 0;
}