程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++ Primer Plus學習筆記之運算符重載

C++ Primer Plus學習筆記之運算符重載

編輯:C++入門知識

C++ Primer Plus學習筆記之運算符重載

1,成員函數和友元函數選擇的建議 下面我們先看兩個例子: 成員函數重載
#include

using namespace std;

class Complex
{
	public:
		Complex(double r=0,double i=0)
		{
			re=r;
			im=i;
		}
		Complex operator+(const Complex& obj);
		Complex operator!();
		void Display();
	private:
		double re;
		double im;
};

Complex Complex::operator+(const Complex& obj)
{
	Complex temp;
	temp.re=re+obj.re;
	temp.im=im+obj.im;
	return temp;
}

Complex Complex::operator!()
{
	Complex temp;
	temp.re=re;
	temp.im=-im;
	return temp;
}

void Complex::Display()
{
	cout<0)
		cout<<"+"<友元函數重載
#include

using namespace std;

class Complex
{
	public:
		Complex(double r=0,double i=0)
		{
			re=r;
			im=i;
		}
		friend Complex operator+(const Complex& obj1,const Complex& obj2);
		Complex operator!();
		void Display();
	private:
		double re;
		double im;
};

Complex operator+(const Complex& obj1,const Complex& obj2)
{
	Complex temp;
	temp.re=obj1.re+obj2.re;
	temp.im=obj1.im+obj2.im;
	return temp;
}

Complex Complex::operator!()
{
	Complex temp;
	temp.re=re;
	temp.im=-im;
	return temp;
}

void Complex::Display()
{
	cout<0)
		cout<<"+"<對於成員函數重載,由於obj3=27+obj1的顯示調用為obj3=27.operator+(obj1),而27不是Complex類型,因此編譯器不能調用Complex的operator+()重載運算符完成加法操作;
對於友元函數重載,由於obj3=27+obj1的調用通過有一個參數缺省的構造函數Complex(double r=0,double i=0),系統可以自動將27轉換為Complex(27)對象,因此編譯通過;
由此可知,成員函數僅僅能為一個實際對象所調用,友元無此限制。因此若運算符的操作需要修改類對象的狀態,則它應該是成員函數,而不應該是友元。相反,如果運算符的操作數(尤其是第一個操作數)希望有隱式類型轉換,則該運算符重載必須用友元函數,而不是成員函數。
2,重載++的前綴和後綴
成員函數重載
#include

using namespace std;

class Complex
{
	public:
		Complex(double r=0,double i=0)
		{
			re=r;
			im=i;
		}
		friend Complex operator+(const Complex& obj1,const Complex& obj2);
		Complex& operator++();//前綴方式
		Complex operator++(int);//後綴方式
		Complex operator!();
		void Display();
	private:
		double re;
		double im;
};

Complex operator+(const Complex& obj1,const Complex& obj2)
{
	Complex temp;
	temp.re=obj1.re+obj2.re;
	temp.im=obj1.im+obj2.im;
	return temp;
}

Complex& Complex::operator++()
{
	re++;
	im++;
	return *this;
}

Complex Complex::operator++(int)//int為占位符
{
	Complex temp(*this);//拷貝構造函數
	re++;
	im++;
	return temp;
}

Complex Complex::operator!()
{
	Complex temp;
	temp.re=re;
	temp.im=-im;
	return temp;
}

void Complex::Display()
{
	cout<0)
		cout<<"+"<#include

using namespace std;

class Complex
{
	public:
		Complex(double r=0,double i=0)
		{
			re=r;
			im=i;
		}
		friend Complex operator+(const Complex& obj1,const Complex& obj2);
		friend Complex& operator++(Complex& obj);//前綴方式
		friend Complex operator++(Complex& obj,int);//後綴方式
		Complex operator!();
		void Display();
	private:
		double re;
		double im;
};

Complex operator+(const Complex& obj1,const Complex& obj2)
{
	Complex temp;
	temp.re=obj1.re+obj2.re;
	temp.im=obj1.im+obj2.im;
	return temp;
}

Complex& operator++(Complex& obj)
{
	obj.re++;
	obj.im++;
	return obj;
}

Complex operator++(Complex& obj,int)//int為占位符
{
	Complex temp(obj);//拷貝構造函數
	obj.re++;
	obj.im++;
	return temp;
}

Complex Complex::operator!()
{
	Complex temp;
	temp.re=re;
	temp.im=-im;
	return temp;
}

void Complex::Display()
{
	cout<0)
		cout<<"+"<#include
#include
#include

using namespace std;

class String
{
	public:
		String()
		{
			msize=0;
			mstr=NULL;
		}
		String(char *str);
		String(const String& str);
		String operator+(const String& str);
		String& operator=(const String& str);
		void Display();
	private:
		char *mstr;
		int msize;
};

String::String(char *str)
{
	if(str==NULL)
	{
		msize=0;
		mstr=NULL;
	}
	else
	{
		msize=strlen(str);
		mstr=new char[msize+1];
		assert(mstr);
		strcpy(mstr,str);
	}
}

String::String(const String& str)
{
	if(str.msize==0)
	{
		msize=0;
		mstr=NULL;
	}
	else
	{
		msize=str.msize;
		mstr=new char[msize+1];
		assert(mstr);
		strcpy(mstr,str.mstr);
	}
}

String String::operator+(const String& str)
{
	String temp;
	temp.msize=msize+str.msize-1;
	temp.mstr=new char[temp.msize];
	assert(temp.mstr);
	strcpy(temp.mstr,mstr);
	strcpy(&(temp.mstr[msize]),str.mstr);
	return temp;
}

String& String::operator=(const String& str)
{
	if(this==&str)
		return *this;
	if(msize>0)
		delete []mstr;
	msize=str.msize;
	mstr=new char[msize];
	assert(mstr);
	strcpy(mstr,str.mstr);
	return *this;
}

void String::Display()
{
	cout<如果用戶沒有定義一個類重載賦值運算符,編譯器將生成一個缺省的賦值運算符。賦值運算符把源對象逐域地拷貝到目的對象;
下面做一個總結,編譯器會自動生成的函數有:
1,構造函數;
2,析構函數;
3,拷貝構造函數;
4,賦值運算符;
拷貝構造函數和賦值運算符的區別是:
拷貝構造函數是要創建一個新的對象,而賦值運算符則是改變一個已經存在的對象的值;
需要注意的是當一個類包含指針類型的數據成員時,最好進行賦值運算符和拷貝構造函數的重載,否則很有可能造成指針懸掛問題(動態申請的空間無法訪問,無法釋放);
4,重載[]運算符
#include
#include
#include

using namespace std;

class String
{
	public:
		String()
		{
			msize=0;
			mstr=NULL;
		}
		String(char *str);
		String(const String& str);
		String operator+(const String& str);
		String& operator=(const String& str);
		char& operator[](int index);//可讀可寫
		char operator[](int index)const;//只讀
		void Display();
	private:
		char *mstr;
		int msize;
};

String::String(char *str)
{
	if(str==NULL)
	{
		msize=0;
		mstr=NULL;
	}
	else
	{
		msize=strlen(str);
		mstr=new char[msize+1];
		assert(mstr);
		strcpy(mstr,str);
	}
}

String::String(const String& str)
{
	if(str.msize==0)
	{
		msize=0;
		mstr=NULL;
	}
	else
	{
		msize=str.msize;
		mstr=new char[msize+1];
		assert(mstr);
		strcpy(mstr,str.mstr);
	}
}

String String::operator+(const String& str)
{
	String temp;
	temp.msize=msize+str.msize-1;
	temp.mstr=new char[temp.msize];
	assert(temp.mstr);
	strcpy(temp.mstr,mstr);
	strcpy(&(temp.mstr[msize]),str.mstr);
	return temp;
}

String& String::operator=(const String& str)
{
	if(this==&str)
		return *this;
	if(msize>0)
		delete []mstr;
	msize=str.msize;
	mstr=new char[msize];
	assert(mstr);
	strcpy(mstr,str.mstr);
	return *this;
}

char& String::operator[](int index)//可讀可寫
{
	return mstr[index-1];
}

char String::operator[](int index)const//只讀,但只能由常對象調用
{
	return mstr[index-1];
}

void String::Display()
{
	cout<重載[]運算符時,我寫了兩個版本,一個可讀可寫,另一個起只讀作用;
注意:只能重載為類成員的操作符有四個=、[]、()、->;
5,輸入輸出重載
#include

using namespace std;

class Complex
{
	public:
		Complex()
		{
			re=0;
			im=0;
		}
		Complex(double r,double i)
		{
			re=r;
			im=i;
		}
		Complex operator+(const Complex& obj);
		Complex operator!();
		friend ostream& operator<<(ostream &os,const Complex &c);
		friend istream& operator>>(istream &is,Complex &c);
	private:
		double re;
		double im;
};

Complex Complex::operator+(const Complex& obj)
{
	Complex temp;
	temp.re=re+obj.re;
	temp.im=im+obj.im;
	return temp;
}

Complex Complex::operator!()
{
	Complex temp;
	temp.re=-re;
	temp.im=-im;
	return temp;
}

ostream& operator<<(ostream &os,const Complex &c)
{
	os<0)
		os<<"+"<>(istream &is,Complex &c)
{
	is>>c.re>>c.im;
	return is;
}

int main(int argc,char *argv[])
{
	Complex obj1(1,2),obj2(3,4);
	Complex obj3=obj1+!obj2;
	cout<>obj3;
	cout<輸入輸出運算符的重載只能用友元函數的方式,應為隱式調用為cout<>,需要注意的是第二個參數必須是對象的引用;

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved