c++學習筆記(運算符重載)


c++為什么要有運算符重載:

C++有許多內置的數據類型,包括int,char,double等,每一種類型都有許多運算符,例如加+,減,乘,除等。當用戶定義了類的對象時,兩個對象之間是不能進行這些操作的,比如對象a+b,這樣的語句如果沒有重載+運算符就會出錯。但C++允許用戶把這些運算符添加到自已的類中以方便類的對象之間的運算就像內置類型的運算一樣方便,比如對象a+b這樣就很明白更容易懂,當然也可以在類中定義一個對象間相加的函數,比如a.add(b)調用函數add()以實現兩個對象a和b相加,但是這條語句沒有比a+b更容易讓人理解。於是就有了運算符重載。

下面具體對+號進行運算符重載實例(實現復數相加)(1,2i)+(2,3i)=(3,5i):

第一種情況不用運算符重載實現:

Complex.h里面:

#ifndef COMPLEX_H_

#define COMPLEX_H_

#include<iostream>

usingnamespace std;

classComplex

{

public:

   Complex(double r = 0,double i = 0);

   ~Complex();

   void show();

   void add(Complex &other);

private:

   doublereal;

   doubleimage;

};

#endif

在Complex.cpp里面:

#include"Complex.h"

Complex::Complex(double r,double i):real(r),image(i)

{}

Complex::~Complex()

{}

void Complex::add(Complex &other)  //無返回值的類型

{

   this->real = this->real + other.real;//這里的this就是指向調用該函數對象的指針

   this->image = this->image + other.image;

   //c1.add(c); c1 = c1 + c實現了復數相加

   this->show();   //打印輸出

}

void Complex::show()

{

   cout<<"("<<real<<","<<image<<")"<<endl;

}

在main.cpp里面:

#include<iostream>

usingnamespace std;

#include"Complex.h"

int main()

{

   Complex c(1,2);

   Complex c1(3,4);

   Complex c2;

   c1.add(c); //實現復數相加無返回值

   return 0;

}

打印出:

(4,6)

 

用帶返回值的情況:

Complex.h里面:

#ifndef COMPLEX_H_

#define COMPLEX_H_

#include<iostream>

usingnamespace std;

classComplex

{

public:

   Complex(double r = 0,double i = 0);

   ~Complex();

   void show();

   Complex add(Complex &other);

private:

   doublereal;

   doubleimage;

};

#endif

在Complex.cpp里面:

#include"Complex.h"

Complex::Complex(double r,double i):real(r),image(i)

{}

Complex::~Complex()

{}

Complex Complex::add(Complex &other)//有返回值的類型

{

   Complex c;

   c.real = this->real + other.real;//這里的this就是指向調用該函數對象的指針

   c.image = this->image + other.image;

   return c;

}

/* 考慮一下此處為什么不返回引用

 * 局部變量不會一直存在如果返回引用局部變量用完即消失引用也就不存在

 * 什么情況下用引用當這個對象在調用前和調用后都存在的情況下,在下面會見到這種情況

 */

void Complex::show()

{

   cout<<"("<<real<<","<<image<<")"<<endl;

}

在main.cpp里面:

#include<iostream>

usingnamespace std;

#include"Complex.h"

int main()

{

   Complex c(1,2);

   Complex c1(3,4);

   Complex c2;

   c2 =c1.add(c); //實現復數相加有返回值

   c2.show();

   return 0;

}

同樣打印出:

(4,6)

用上面這兩種做法來實現復數相加,雖然實現了,單程序的可讀性不強,拿到主程序一看不知道要實現什么功能,所以一般不要這種,下面介紹用運算符重載的辦法來實現:

第二種情況用運算符重載實現:

運算符重載實質上就是函數的重載

1、用調用成員函數的方法:

Complex.h里面:

#ifndef COMPLEX_H_

#define COMPLEX_H_

#include<iostream>

usingnamespace std;

classComplex

{

public:

   Complex(double r = 0,double i = 0);

   ~Complex();

   void show();

   Complex operator+(Complex &other);//用成員函數的方法重載運算符+

private:

   doublereal;

   doubleimage;

};

#endif

在Complex.cpp里面:

#include"Complex.h"

Complex::Complex(double r,double i):real(r),image(i)

{}

Complex::~Complex()

{}

Complex Complex::operator+(Complex &other)

{

   Complex c;

   c.real = this->real + other.real;//這里的this就是指向調用該函數對象的指針

   c.image = this->image + other.image;

   return c;

}

/* 考慮一下此處為什么不返回引用

 * 局部變量不會一直存在如果返回引用局部變量用完即消失引用也就不存在

 * 什么情況下用引用當這個對象在調用前和調用后都存在的情況下,在下面會見到這種情況

 */

void Complex::show()

{

   cout<<"("<<real<<","<<image<<")"<<endl;

}

在main.cpp里面:

#include<iostream>

usingnamespace std;

#include"Complex.h"

int main()

{

   Complex c(1,2);

   Complex c1(3,4);

   Complex c2;

   c2 =c1+c; //實現復數相加有返回值

   //本質是 c2 = c1.operator+(c);operator+()是個函數

   c2.show();

   return 0;

}

同樣打印出:

(4,6)

相比前兩個程序而言這個程序一看就知道要實現什么,和我們常使用的加法一樣。

 

1、用調用友元函數的方法(只需改動函數):

Complex.h里面:

#ifndef COMPLEX_H_

#define COMPLEX_H_

#include<iostream>

usingnamespace std;

classComplex

{

public:

   Complex(double r = 0,double i = 0);

   ~Complex();

   void show();

   friendComplex operator+(Complex& c1,Complex&c2);//用友元函數的方法重載運算符+

private:

   doublereal;

   doubleimage;

};

#endif

在Complex.cpp里面:

#include"Complex.h"

Complex::Complex(double r,double i):real(r),image(i)

{}

Complex::~Complex()

{}

Complex operator+(Complex& c1,Complex&c2)//用友元定義

{

   Complex c;

   c.real = c1.real + c2.real//在這里就不能用this指針了,因為友元不是該類的成員函數

   c.image = c1.image + c2.image;

   return c;

}

/* 考慮一下此處為什么不返回引用

 * 局部變量不會一直存在如果返回引用局部變量用完即消失引用也就不存在

 * 什么情況下用引用當這個對象在調用前和調用后都存在的情況下,在下面會見到這種情況

 */

void Complex::show()

{

   cout<<"("<<real<<","<<image<<")"<<endl;

}

在main.cpp里面:

#include<iostream>

usingnamespace std;

#include"Complex.h"

int main()

{

   Complex c(1,2);

   Complex c1(3,4);

   Complex c2;

   c2 =c1+c; //實現復數相加有返回值

   //用友元的本質 c2 = operator(c1,c);

   c2.show();

   return 0;

}

同樣打印出:

(4,6)

什么時候用友元什么時候用成員函數???

一般情況下,一元運算符重載為成員函數,二元運算符重載為友元函數.(個例除外)

上面重載+號就是一個雙目運算符應該要用友元。。

下面在重載一個單目運算符如-(負號)

Complex.h里面:

#ifndef COMPLEX_H_

#define COMPLEX_H_

#include<iostream>

usingnamespace std;

classComplex

{

public:

   Complex(double r = 0,double i = 0);

   ~Complex();

   void show();

   Complex& operator-();//用成員函數重載負號

   friendComplex operator+(Complex& c1,Complex&c2);//用友元函數的方法重載運算符+

private:

   doublereal;

   doubleimage;

};

#endif

在Complex.cpp里面:

#include"Complex.h"

Complex::Complex(double r,double i):real(r),image(i)

{}

Complex::~Complex()

{}

Complex operator+(Complex& c1,Complex&c2)//用友元定義

{

   Complex c;

   c.real = c1.real + c2.real//在這里就不能用this指針了,因為友元不是該類的成員函數

   c.image = c1.image + c2.image;

   return c;

}

/* 考慮一下此處為什么不返回引用

 * 局部變量不會一直存在如果返回引用局部變量用完即消失引用也就不存在

 * 什么情況下用引用當這個對象在調用前和調用后都存在的情況下,在下面會見到這種情況

 */

Complex& Complex::operator-()//c2一直存在可以考慮返回引用

{

   this->real = -this->real;

   this->image =-this->image;

   return *this;

}

void Complex::show()

{

   cout<<"("<<real<<","<<image<<")"<<endl;

}

在main.cpp里面:

#include<iostream>

usingnamespace std;

#include"Complex.h"

int main()

{

   Complex c(1,2);

   Complex c1(3,4);

   Complex c2;

   c2 =c1+c; //實現復數相加有返回值

   //用友元的本質 c2 = operator(c1,c);

   c2.show();

   c2 = -c2; //c2取負

   //本質就是 c2.operator -();

   c2.show();

   return 0;

}

打印出:

(4,6)

(-4,-6)

緊接着再來重載一個++ -- ++分為前加加和后加加。

Complex.h里面:

#ifndef COMPLEX_H_

#define COMPLEX_H_

#include<iostream>

usingnamespace std;

classComplex

{

public:

   Complex(double r = 0,double i = 0);

   ~Complex();

   void show();

   Complex& operator++(); //前加加

   Complex& operator-();//用成員函數重載負號

   friendComplex operator+(Complex& c1,Complex&c2);//用友元函數的方法重載運算符+

private:

   doublereal;

   doubleimage;

};

#endif

在Complex.cpp里面:

#include"Complex.h"

Complex::Complex(double r,double i):real(r),image(i)

{}

Complex::~Complex()

{}

Complex operator+(Complex& c1,Complex&c2)//用友元定義

{

   Complex c;

   c.real = c1.real + c2.real//在這里就不能用this指針了,因為友元不是該類的成員函數

   c.image = c1.image + c2.image;

   return c;

}

Complex& Complex::operator-()//c2一直存在可以考慮返回引用

{

   this->real = -this->real;

   this->image =-this->image;

   return *this;

}

Complex& Complex::operator++()//前加加

{

   this->real++;

   this->image++;

   return *this;

}

void Complex::show()

{

   cout<<"("<<real<<","<<image<<")"<<endl;

}

在main.cpp里面:

#include<iostream>

usingnamespace std;

#include"Complex.h"

int main()

{

   Complex c(1,2);

   Complex c1(3,4);

   Complex c2;

   c2 =c1+c; //實現復數相加有返回值

   //用友元的本質 c2 = operator(c1,c);

   c2.show();

   c2 = -c2; //c2取負

   //本質就是 c2.operator -();

   c2.show();

   ++c2;   //前加加就是先加加后使用

   c2.show();

   return 0;

}

打印出:

(4,6)

(-4,-6)

(-3,-5)

可能你會發現前加加是++而后加加也是++那這兩個要怎么區分呢?

c++約定 ++或--運算符重載函數中如果形參為空則為前++。

如果形參增加一個int則為后++ 此時的hint無實際意義,僅作為后置與前置 俗稱啞元。

下面看后加加

Complex.h里面:

#ifndef COMPLEX_H_

#define COMPLEX_H_

#include<iostream>

usingnamespace std;

classComplex

{

public:

   Complex(double r = 0,double i = 0);

   ~Complex();

   void show();

   Complex& operator++(); //前加加

   Complex operator++(int);//后加加

   Complex& operator-();//用成員函數重載負號

   friendComplex operator+(Complex& c1,Complex&c2);//用友元函數的方法重載運算符+

private:

   doublereal;

   doubleimage;

};

#endif

在Complex.cpp里面:

#include"Complex.h"

Complex::Complex(double r,double i):real(r),image(i)

{}

Complex::~Complex()

{}

Complex operator+(Complex& c1,Complex&c2)//用友元定義

{

   Complex c;

   c.real = c1.real + c2.real//在這里就不能用this指針了,因為友元不是該類的成員函數

   c.image = c1.image + c2.image;

   return c;

}

Complex& Complex::operator-()//c2一直存在可以考慮返回引用

{

   this->real = -this->real;

   this->image =-this->image;

   return *this;

}

Complex& Complex::operator++()//前加加

{

   this->real++;

   this->image++;

   return *this;

}

Complex Complex::operator++(int)//后加加

{

   Complex tem(*this);//把原來的值用變量保存起來

   this->real++;

   this->image++;

   return tem;

}

void Complex::show()

{

   cout<<"("<<real<<","<<image<<")"<<endl;

}

在main.cpp里面:

#include<iostream>

usingnamespace std;

#include"Complex.h"

int main()

{

   Complex c(1,2);

   Complex c1(3,4);

   Complex c2;

   c2 =c1+c; //實現復數相加有返回值

   //用友元的本質 c2 = operator(c1,c);

   c2.show();

   c2 = -c2; //c2取負

   //本質就是 c2.operator -();

   c2.show();

   ++c2;   //前加加就是先加加后使用

   c2.show();

   Complex cc;

   cc = c2++; //后加加是先使用在加加

   cc.show(); //使用的值

   c2.show(); //加加后的值

   return 0;

}

打印出:

(4,6)

(-4,-6)

(-3,-5)   //

(-3,-5)   // 先使用c2的值正確

(-2,-4)

寫到這里應該對運算符重載有一定了解了,下面下點總結:

/*

 * 1、系統默認了,賦值運算符重載,如無需深賦值,無需重寫

 * 2、運算符重載的本質是函數重載

 * 格式:

 * 函數類型 opertaor@(形參列表)

 * {

 *    重載處理語句

 * }

 * 3c++只能重載現有的運算符,並且在現有的運算符當中有如下不能重載:

 * ?:條件運算符

 * .成員運算符

 * .*成員指針運算符

 * ::作用域運算符

 * sizeof 類型長度運算符

 * 4、重載運算符不要改變語意,不要改變結合,優先級,對象參數的個數

 * 5、運算符重載函數不能有默認參數

 * 6、運算符重載函數中,必須和一個自定義類一起使用。

 */

/*

 * 1、運算符重載函數既可以是成員函數,也可以是友元函數(<< >>只能重載為友元)

 * 2、運算符重載函數為成員函數時,比重載為友元函數少一個參數由this引進。

 * 3、一般情況下,一元運算符重載為成員函數,二元運算符重載為友元函數.(個例除外)

 *

 * <<流插入運算符 >>流提取運算符已被系統重載

 * ostream& operator<<(ostream &os,自定義類&);

 * istream& operator<<(ostream &os,自定義類&);

 *

 * c++約定 ++--運算符重載函數中如果形參為空則為前++

 * 如果形參增加一個int則為后++ 此時的hint無實際意義,僅作為后置與前置啞元

 */

雖然系統已經把<<>>已經重載了,但還是希望能用用插入運算符“<<”來輸出用戶自己聲明的類的對象的信息。

下面就來重載一下”<<””>>”符。

這里需要知道的是 我們常用到的cin和cout起始是ostreamistream類的對象,所以我們每次包含頭文件時都要加上#include<iostream>就是這個道理。

Complex.h里面:

#ifndef COMPLEX_H_

#define COMPLEX_H_

#include<iostream>

usingnamespace std;

classComplex

{

public:

   Complex(double r = 0,double i = 0);

   ~Complex();

   void show();

   Complex& operator++(); //前加加

   Complex operator++(int);//后加加

   Complex& operator-();//用成員函數重載負號

   friendComplex operator+(Complex& c1,Complex&c2);//用友元函數的方法重載運算符+

   friendostream& operator<<(ostream& os,Complex& c);//用友元函數重載運算符<<

private:

   doublereal;

   doubleimage;

};

#endif

在Complex.cpp里面:

#include"Complex.h"

Complex::Complex(double r,double i):real(r),image(i)

{} 

Complex::~Complex()

{}

Complex operator+(Complex& c1,Complex&c2)//用友元定義

{

   Complex c;

   c.real = c1.real + c2.real//在這里就不能用this指針了,因為友元不是該類的成員函數

   c.image = c1.image + c2.image;

   return c;

}

Complex& Complex::operator-()//c2一直存在可以考慮返回引用

{

   this->real = -this->real;

   this->image =-this->image;

   return *this;

}

Complex& Complex::operator++()//前加加

{

   this->real++;

   this->image++;

   return *this;

}

Complex Complex::operator++(int)//后加加

{

   Complex tem(*this);//把原來的值用變量保存起來

 

   this->real++;

   this->image++;

   return tem;

}

ostream& operator<<(ostream& os,Complex& c)

{

   os<<"("<<c.real<<","<<c.image<<")"<<endl;

   return os;

}

void Complex::show()

{

   cout<<"("<<real<<","<<image<<")"<<endl;

}

在main.cpp里面:

#include<iostream>

usingnamespace std;

#include"Complex.h"

int main()

{

   Complex c(1,2);

   Complex c1(3,4);

   Complex c2;

   c2 =c1+c; //實現復數相加有返回值

   //用友元的本質 c2 = operator(c1,c);

   c2.show();

   c2 = -c2; //c2取負

   //本質就是 c2.operator -();

   c2.show();

   ++c2;   //前加加就是先加加后使用

   c2.show();

   Complex cc;

   cc = c2++; //后加加是先使用在加加

// cc.show(); //使用的值

// c2.show(); //加加后的值

   //這時我們就可以直接輸出對象

   cout<<cc<<c2;  //輸出對象

    //本質是就是operator<<(operator<<(cout,c2),c) 這就是有返回值的好處可以連續輸出

   return 0;

}

同樣打印出:

(4,6)

(-4,-6)

(-3,-5)

(-3,-5)

(-2,-4)

這樣的輸出更直接。。

現在再來重載>>應該就很簡單了:

Complex.h里面:

#ifndef COMPLEX_H_

#define COMPLEX_H_

#include<iostream>

usingnamespace std;

classComplex

{

public:

   Complex(double r = 0,double i = 0);

   ~Complex();

   void show();

   Complex& operator++(); //前加加

   Complex operator++(int);//后加加

   Complex& operator-();//用成員函數重載負號

   friendComplex operator+(Complex& c1,Complex&c2);//用友元函數的方法重載運算符+

   friendostream& operator<<(ostream& os,Complex& c);//用友元函數重載運算符<<

   friendistream& operator>>(istream& is,Complex& c);//用友元函數重載運算符<<

private:

   doublereal;

   doubleimage;

};

#endif

在Complex.cpp里面:

#include"Complex.h"

Complex::Complex(double r,double i):real(r),image(i)

{} 

Complex::~Complex()

{}

Complex operator+(Complex& c1,Complex&c2)//用友元定義

{

   Complex c;

   c.real = c1.real + c2.real//在這里就不能用this指針了,因為友元不是該類的成員函數

   c.image = c1.image + c2.image;

   return c;

}

Complex& Complex::operator-()//c2一直存在可以考慮返回引用

{

   this->real = -this->real;

   this->image =-this->image;

   return *this;

}

Complex& Complex::operator++()//前加加

{

   this->real++;

   this->image++;

   return *this;

}

Complex Complex::operator++(int)//后加加

{

   Complex tem(*this);//把原來的值用變量保存起來

 

   this->real++;

   this->image++;

   return tem;

}

ostream& operator<<(ostream& os,Complex& c)

{

   os<<"("<<c.real<<","<<c.image<<")"<<endl;

   return os;

}

istream& operator>>(istream& is,Complex& c)

{

   is>>c.real>>c.image;

   return is;

}

void Complex::show()

{

   cout<<"("<<real<<","<<image<<")"<<endl;

}

在main.cpp里面:

#include<iostream>

usingnamespace std;

#include"Complex.h"

int main()

{

   Complex c(1,2);

   Complex c1(3,4);

   Complex c2;

   c2 =c1+c; //實現復數相加有返回值

   //用友元的本質 c2 = operator(c1,c);

   c2.show();

   c2 = -c2; //c2取負

   //本質就是 c2.operator -();

   c2.show();

   ++c2;   //前加加就是先加加后使用

   c2.show();

   Complex cc;

   cc = c2++; //后加加是先使用在加加

// cc.show(); //使用的值

// c2.show(); //加加后的值

   //這時我們就可以直接輸出對象

   cout<<cc<<c2;  //輸出對象

    //本質是就是operator<<(operator<<(cout,c2),c) 這就是有返回值的好處可以連續輸出

   cin>>c2; //輸入對象的值

   cout<<c2; //輸出

   return 0;

}

打印:

(4,6)

(-4,-6)

(-3,-5)

(-3,-5)

(-2,-4)

5 6    //輸入5 6

(5,6) //打印出 5 6

以上程序都是驗證過的,大家可以試一下,相信把這幾個程序弄懂了,c++運算符重載也就弄懂的差不多了。


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com