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<>,需要注意的是第二個參數必須是對象的引用;