C++用顶层函数重载操作符
幾句話總結:以頂層函數的形式重載操作符時,二元操作符重載函數必須有兩個參數,一元操作符重載必須有一個參數。以頂層函數的形式重載操作符時的好處是:
2用成員函數時會報錯。具體看下面解釋。但是用頂層函數不會。但是頂層函數實現時,不能直接調用類里面的私有成員,改進的方式是把頂層函數設為該類的友元函數。
?
在前面將操作符重載函數聲明為類成員函數時,我們不斷強調二元操作符,其函數參數為一個,一元操作符重載函數不需要函數參數。如果以頂層函數的形式重載操作符時,二元操作符重載函數必須有兩個參數,一元操作符重載必須有一個參數。
以頂層函數的形式重載操作符,從函數實現上來看其實現相對于以類成員函數的形式實現起來要復雜一些,因為在類外無法直接訪問類的私有成員變量。但是以頂層函數的形式來重載操作符有自身的優勢,我們來看下面的示例。
?
本例中是以成員函數的形式進行操作符重載的,在主函數中我們定義了兩個complex復數類的對象,語句“c1 = c2 + 13.5;”是將c2與一個double類型的數據相加,我們可以將其理解為:
? ? c1 = c2.operator+(13.5);
因為我們在類中定義了一個只帶一個參數的構造函數complex(double a);,這個構造函數其實可以視為轉型構造函數,它可以將double類型轉換為一個complex類對象。因此 “c1 = c2 + 13.5;”語句其實也是相當于兩個復數類對象相加。當然,如果在類中沒有定義complex(double a);這樣一個只帶一個參數的構造函數,那么這一句也是有語法問題的,因為我們重載的加法只適用于兩個complex類對象相加,而系統內建的又只能用于兩個普通數據類型的操作數相加,一個complex類對象和一個普通數據類型的操作數相加,系統是無法去處理這樣的異常情況的。
我們再來看一下后面一個語句“c1 = 13.5 + c2;”,這一語句我們可以將其理解為:
??? c1 = 13.5.operator+(c2);
如此一來,這一句的問題非常明顯,13.5只是一個double類型的常數,它不是類對象,因此也不可能有調用operator+的能力。雖然我們在類中定義了一個具有一個參數的構造函數,但是編譯器將語句“c1 = 13.5 + c2;”理解成“c1 = 13.5.operator+(c2);”并不會將13.5轉換成一個complex類對象,因為編譯器遇到這種情況并不會產生一種很智能的處理,同樣它也并不知道程序設計人員的意圖。所以例3中語句“c1 = 13.5 + c2;”是有語法錯誤的。
例4
#include <iostream> using namespace std;class complex { public:complex();complex(double a);complex(double a, double b);double getreal() const { return real; }double getimag() const { return imag; }void setreal(double a){ real = a; }void setimag(double b){ imag = b; }void display()const; private:double real; //復數的實部double imag; //復數的虛部 };complex::complex() {real = 0.0;imag = 0.0; }complex::complex(double a) {real = a;imag = 0.0; }complex::complex(double a, double b) {real = a;imag = b; }//打印復數 void complex::display()const {cout<<real<<" + "<<imag<<" i "; }//重載加法操作符 complex operator+(const complex & A, const complex &B) {complex C;C.setreal(A.getreal() + B.getreal());C.setimag(A.getimag() + B.getimag());return C; }//重載減法操作符 complex operator-(const complex & A, const complex &B) {complex C;C.setreal(A.getreal() - B.getreal());C.setimag(A.getimag() - B.getimag());return C; }//重載乘法操作符 complex operator*(const complex & A, const complex &B) {complex C;C.setreal(A.getreal() * B.getreal() - A.getimag() * B.getimag() );C.setimag(A.getimag() * B.getreal() + A.getreal() * B.getimag() );return C; }//重載除法操作符 complex operator/(const complex & A, const complex & B) {complex C;double square = A.getreal() * A.getreal() + A.getimag() * A.getimag();C.setreal((A.getreal() * B.getreal() + A.getimag() * B.getimag())/square);C.setimag((A.getimag() * B.getreal() - A.getreal() * B.getimag())/square);return C; }int main() {complex c1, c2(15.5, 23.1);c1 = c2 + 13.5;c1 = 13.5 + c2;return 0; }我們再來看一下例4,這個例子則是以頂層函數的形式定義操作符重載函數。我們同樣來看主函數,主函數定義了c1和c2兩個complex類對象。先來看一下語句“c1 = c2 + 13.5;”,這個語句可以理解如下:
??? c1 = operator+(c2, 13.5);
因為我們在頂層函數中定義了complex operator+(const complex & A, const complex &B)函數,系統在執行“c1 = operator+(c2, 13.5);”時找到了對應的頂層函數,但是發現參數不對,但是可以通過類的構造函數將13.5轉換成complex類對象,如此就滿足operator+函數的調用條件了,故而這一句是沒有問題的。
我們再來看一下語句“c1 = 13.5 + c2;”,這一語句可以理解為:
??? c1 = operator+(13.5, c2);
這一句的執行與“c1 = operator+(c2, 13.5);”是一樣的,它可以利用類的構造函數將13.5轉換為complex類對象,因此這一句也是可以正確執行的。
從例3和例4兩個例子中,我們不難看出雖然實現麻煩的以頂層函數的形式進行操作符重載的優勢所在了。我們總結一下,以類成員函數的形式進行操作符重載,操作符左側的操作數必須為類對象;而以頂層函數的形式進行操作符重載,只要類中定義了相應的轉型構造函數,操作符左側或右側的操作數均可以不是類對象,但其中必須至少有一個類對象,否則調用的就是系統內建的操作符而非自己定義的操作符重載函數了。
例5:
#include <iostream> using namespace std;class complex { public:complex();complex(double a);complex(double a, double b);friend complex operator+(const complex & A, const complex & B);friend complex operator-(const complex & A, const complex & B);friend complex operator*(const complex & A, const complex & B);friend complex operator/(const complex & A, const complex & B);void display()const; private:double real; //復數的實部double imag; //復數的虛部 };complex::complex() {real = 0.0;imag = 0.0; }complex::complex(double a) {real = a;imag = 0.0; }complex::complex(double a, double b) {real = a;imag = b; }//打印復數 void complex::display()const {cout<<real<<" + "<<imag<<" i "; }//重載加法操作符 complex operator+(const complex & A, const complex &B) {complex C;C.real = A.real + B.real;C.imag = A.imag + B.imag;return C; }//重載減法操作符 complex operator-(const complex & A, const complex &B) {complex C;C.real = A.real - B.real;C.imag = A.imag - B.imag;return C; }//重載乘法操作符 complex operator*(const complex & A, const complex &B) {complex C;C.real = A.real * B.real - A.imag * B.imag;C.imag = A.imag * B.real + A.real * B.imag;return C; }//重載除法操作符 complex operator/(const complex & A, const complex & B) {complex C;double square = A.real * A.real + A.imag * A.imag;C.real = (A.real * B.real + A.imag * B.imag)/square;C.imag = (A.imag * B.real - A.real * B.imag)/square;return C; }int main() {complex c1(4.3, -5.8);complex c2(8.4, 6.7);complex c3;c3 = c1 + c2;cout<<"c1 + c2 = ";c3.display();cout<<endl;c3 = c1 - c2;cout<<"c1 - c2 = ";c3.display();cout<<endl;c3 = c1 * c2;cout<<"c1 * c2 = ";c3.display();cout<<endl;c3 = c1 / c2;cout<<"c1 / c2 = ";c3.display();cout<<endl;return 0; }本例就是采用友元函數的形式進行操作符重載,如此實現既能繼承操作符重載函數是頂層函數的優勢,同時又能夠使操作符重載函數實現起來更簡單。
總結
以上是生活随笔為你收集整理的C++用顶层函数重载操作符的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++重载操作符的优先级
- 下一篇: 单片机联网,UIP实现tcp/udp协议