国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C++ > 正文

C++教程:C++操作符的重載

2020-05-23 14:25:42
字體:
來源:轉載
供稿:網友
在表達式中,我們常會用到各種操作符(運算符),例如1+3和4*2。然而,這些操作符只能用于C++內置的一些基本數據類型。如果我們自己編寫一個復數類,它也會有加減法的操作,那么它能否擺脫一串冗長的函數名,而享用加號呢?

在第六章我們學到過,函數是可以重載的,即同名函數針對不同數據類型的參數實現類似的功能。在C++中,操作符也是可以重載的,同一操作符對于不同的自定義數據類型可以進行不同的操作。

作為成員函數

在我們學習操作符重載前,我們先看看原先這個復數類是如何定義的:(程序16.3.1)
//complex.h
#include <iostream>
using namespace std;
class Complex//聲明一個復數類
{
   public:
   Complex(Complex &a);//拷貝構造函數
   Complex(double r=0,double i=0);
   void display();//輸出復數的值
   void set(Complex &a);
   Complex plus(Complex a);//復數的加法
   Complex minus(Complex a); //復數的減法
   Complex plus(double r); //復數與實數相加
   Complex minus(double r); //復數與實數相減
   private:
   double real;//復數實部
   double img;//復數虛部
};
Complex::Complex(Complex &a)
{
   real=a.real;
   img=a.img;
}
Complex::Complex(double r,double i)
{
   real=r;
   img=i;
}
void Complex::display()
{
   cout <<real <<(img>=0?"+":"") <<img <<"i";//適合顯示1-3i等虛部為負值的復數
}
void Complex::set(Complex &a)
{
   real=a.real;
   img=a.img;
}
Complex Complex::plus(Complex a)
{
   Complex temp(a.real+real,a.img+img);
   return temp;
}
Complex Complex::minus(Complex a)
{
   Complex temp(real-a.real,img-a.img);
   return temp;
}
Complex Complex::plus(double r)
{
   Complex temp(real+r,img);
   return temp;
}
Complex Complex::minus(double r)
{
   Complex temp(real-r,img);
   return temp;
}

//main.cpp
#include "complex.h"
#include <iostream>
using namespace std;
int main()
{
   Complex a(3,2),b(5,4),temp;
   temp.set(a.plus(b));//temp=a+b
   temp.display();
   cout <<endl;
   temp.set(a.minus(b));//temp=a-b
   temp.display();
   cout <<endl;
   return 0;
}
運行結果:
8+6i
-2-2i

雖然程序16.3.1已經實現了復數的加減法,但是其表達形式極為麻煩,如果有復數a、b、c和d,要計算a+b-(c+d)將會變得非常復雜。如果不是調用函數,而是使用操作符的話,就會直觀得多了。

聲明一個操作符重載的語句格式為:
    返回值類型operator 操作符(參數表);

事實上,在聲明和定義操作符重載的時候,我們可以將其看作函數了,只不過這個函數名是一些操作符。在聲明和定義操作符重載時需要注意以下幾點:
  1. 操作符只能是C++中存在的一些操作符,自己編造的操作符是不能參與操作符重載的。另外,“::”(域解析操作符)、“.”(成員操作符)、“……?……:……”(條件操作符)和sizeof等操作符不允許重載。
  2. 參數表中羅列的是操作符的各個操作數。重載后操作數的個數應該與原來相同。不過如果操作符作為成員函數,則調用者本身是一個操作數,故而參數表中會減少一個操作數。(請對比程序16.3.2與程序16.3.3)
  3. 各個操作數至少要有一個是自定義類型的數據,如結構或類。
  4. 盡量不要混亂操作符的含義。如果把加號用在減法上,會使程序的可讀性大大下降。

下面我們把操作符作為成員函數,來實現復數的加減法:(程序16.3.2)
//complex.h
#include <iostream>
using namespace std;
class Complex//聲明一個復數類
{
   public:
   Complex(Complex &a);
   Complex(double r=0,double i=0);
   void display();
   void operator =(Complex a);//賦值操作
   Complex operator +(Complex a);//加法操作
   Complex operator -(Complex a);//減法操作
   Complex operator +(double r);//加法操作
   Complex operator -(double r);//減法操作
   private:
   double real;
   double img;
};
//未定義的函數與程序16.3.1相同
void Complex::operator =(Complex a)
{
   real=a.real;
   img=a.img;
}
Complex Complex::operator +(Complex a)
{
   Complex temp(a.real+real,a.img+img);
   return temp;
}
Complex Complex::operator -(Complex a)
{
   Complex temp(real-a.real,img-a.img);
   return temp;
}
Complex Complex::operator +(double r)
{
   Complex temp(real+r,img);
   return temp;
}
Complex Complex::operator -(double r)
{
   Complex temp(real-r,img);
   return temp;
}
//main.cpp
#include "complex.h"
#include <iostream>
using namespace std;
int main()
{
   Complex a(3,2),b(5,4),c(1,1),d(4,2),temp;
   temp=a+b;//這樣的復數加法看上去很直觀
   temp.display();
   cout <<endl;
   temp=a-b;
   temp.display();
   cout <<endl;
   temp=a+b-(c+d);//可以和括號一起使用了
   temp.display();
   cout <<endl;
   return 0;
}

運行結果:
8+6i
-2-2i
3+3i
以上程序的main.cpp中,復數的加法表達得非常簡潔易懂,與程序16.3.1相比有了很大的進步。并且,我們發現使用了括號以后,可以更方便地描述各種復雜的運算。操作符在重載之后,結合性和優先級是不會發生變化的,符合用戶本來的使用習慣。

作為友元

前面我們把操作符作為成員函數,實現了復數的加減法。如果我們把操作符作為普通的函數重載,則需要將其聲明為友元。這時,參數表中的操作數個數應該與操作符原來要求的操作數個數相同。

下面我們來看一下,用友元和操作符重載來實現復數的加減法:(程序16.3.3)
//complex.h
#include <iostream.h>//由于VC編譯器存在問題,這里使用標準的寫法居然無法通過編譯
class Complex
{
   public:
   Complex(Complex &a);
   Complex(double r=0,double i=0);
   void display();
   friend Complex operator +(Complex a,Complex b);//作為友元
   friend Complex operator -(Complex a,Complex b);
   friend Complex operator +(Complex a,double r);
   friend Complex operator -(Complex a,double r);
   private:
   double real;
   double img;
};
//未定義的函數與程序16.3.1相同
Complex operator +(Complex a,Complex b)
{
   Complex temp(a.real+b.real,a.img+b.img);
   return temp;
}
Complex operator -(Complex a,Complex b)
{
   Complex temp(a.real-b.real,a.img-b.img);
   return temp;
}
Complex operator +(Complex a,double r)
{
   Complex temp(a.real+r,a.img);
   return temp;
}
Complex operator -(Complex a,double r)
{
   Complex temp(a.real-r,a.img);
   return temp;
}
//main.cpp
#include "complex.h"
#include <iostream.h>//由于VC編譯器存在問題,這里使用標準的寫法無法通過編譯
int main()
{
   Complex a(3,2),b(5,4),c(1,1),d(4,2),temp;
   temp=a+b;
   temp.display();
   cout <<endl;
   temp=a-b;
   temp.display();
   cout <<endl;
   temp=a+b-(c+d);
   temp.display();
   cout <<endl;
   return 0;
}

運行結果:
8+6i
-2-2i
3+3i

在上面這個程序中,加號和減號操作符由成員函數變成了友元函數。細心的讀者可能注意到了,那個賦值操作符的定義跑哪兒去了?

事實上,賦值操作符有點類似于默認拷貝構造函數,也具有默認的對象賦值功能。所以即使沒有對它進行重載,也能使用它對對象作賦值操作。但是如果要對賦值操作符進行重載,則必須將其作為一個成員函數,否則程序將無法通過編譯。

在操作符重載中,友元的優勢盡顯無遺。特別是當操作數為幾個不同類的對象時,友元不失為一種良好的解決辦法。

又見加加和減減

在第五章我們學習了增減量操作符,并且知道它們有前后之分。那么增減量操作符是如何重載的呢?同樣是一個操作數,它又是如何區分前增量和后增量的呢?

前增量操作符是“先增后賦”,在操作符重載中我們理解為先做自增,然后把操作數本身返回。后增量操作符是“先賦后增”,在這里我們理解為先把操作數的值返回,然后操作數自增。所以,前增量操作返回的是操作數本身,而后增量操作返回的只是一個臨時的值。

在C++中,為了區分前增量操作符和后增量操作符的重載,規定后增量操作符多一個整型參數。這個參數僅僅是用于區分前增量和后增量操作符,不參與到實際運算中去。

下面我們就來看看,如何重載增量操作符:(程序16.3.4)
//complex.h
#include <iostream.h>//由于VC編譯器存在問題,這里使用標準的寫法無法通過編譯
class Complex
{
   public:
   Complex(Complex &a);
   Complex(double r=0,double i=0);
   void display();
   friend Complex operator +(Complex a,Complex b);
   friend Complex operator -(Complex a,Complex b);
   friend Complex operator +(Complex a,double r);
   friend Complex operator -(Complex a,double r);
   friend Complex& operator ++(Complex &a);//前增量操作符重載
   friend Complex operator ++(Complex &a,int); //后增量操作符重載
   private:
   double real;
   double img;
};
//未定義的函數與程序16.3.3相同
Complex& operator ++(Complex &a)
{
   a.img++;
   a.real++;
   return a;//返回類型為Complex的引用,即返回操作數a本身
}
Complex operator ++(Complex &a,int)//第二個整型參數表示這是后增量操作符
{
   Complex temp(a);
   a.img++;
   a.real++;
   return temp;//返回一個臨時的值
}
//main.cpp
#include "complex.h" 
#include <iostream.h>//由于VC編譯器存在問題,這里使用標準的寫法無法通過編譯
int main()
{
   Complex a(2,2),b(2,4),temp;
   temp=(a++)+b;
   temp.display();
   cout <<endl;
   temp=b-(++a);
   temp.display();
   cout <<endl;
   a.display();
   cout <<endl;
   return 0;
}

運行結果:
4+6i
-2+0i
4+4i

根據運行結果,可以看到a++和++a被區分開來了。而調用后增量操作符的時候,操作數仍然只有一個,與那個用于區分的整型參數無關。

至此,我們已經學完了類的一些基本特性和要素。在接下來的章節中,我們要更深入地發掘面向對象程序設計的優勢。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 长治市| 玉屏| 怀远县| 治县。| 玛纳斯县| 渝中区| 车致| 和平区| 屏边| 庄浪县| 防城港市| 邹平县| 吉木乃县| 奎屯市| 西昌市| 鹤岗市| 清远市| 延川县| 阳泉市| 崇州市| 鹿泉市| 洪洞县| 青龙| 西吉县| 潢川县| 湖南省| 昆明市| 西平县| 鲜城| 伊春市| 南乐县| 永年县| 永福县| 巧家县| 保定市| 宣武区| 永川市| 广东省| 潍坊市| 牙克石市| 根河市|