C++類型轉換函數(類型轉換運算符函數)


用轉換構造函數可以將一個指定類型的數據轉換為類的對象。但是不能反過來將一個類的對象轉換為一個其他類型的數據(例如將一個Complex類對象轉換成double類型數據)。

C++提供類型轉換函數(type conversion function)來解決這個問題。類型轉換函數的作用是將一個類的對象轉換成另一類型的數據。如果已聲明了一個Complex類,可以在Complex類中這樣定義類型轉換函數:
    operator double( )
    {
        return real;
    }
函數返回double型變量real的值。它的作用是將一個Complex類對象轉換為一個double型數據,其值是Complex類中的數據成員real的值。請注意,函數名是operator double,這點是和運算符重載時的規律一致的(在定義運算符“+”的重載函數時,函數名是operator +)。

類型轉換函數的一般形式為:
    operator 類型名( )
    {
        實現轉換的語句
    }
在函數名前面不能指定函數類型,函數沒有參數。其返回值的類型是由函數名中指定的類型名來確定的。類型轉換函數只能作為成員函數,因為轉換的主體是本類的對象。不能作為友元函數或普通函數。

從函數形式可以看到,它與運算符重載函數相似,都是用關鍵字operator開頭,只是被重載的是類型名。double類型經過重載后,除了原有的含義外,還獲得新的含義(將一個Complex類對象轉換為double類型數據,並指定了轉換方法)。這樣,編譯系統不僅能識別原有的double型數據,而且還會把Complex類對象作為double型數據處理。

那么程序中的Complex類對具有雙重身份,既是Complex類對象,又可作為double類型數據。Complex類對象只有在需要時才進行轉換,要根據表達式的上下文來決定。轉換構造函數和類型轉換運算符有一個共同的功能:當需要的時候,編譯系統會自動調用這些函數,建立一個無名的臨時對象(或臨時變量)。

[例10.9] 使用類型轉換函數的簡單例子。

  1. #include <iostream>
  2. using namespace std;
  3. class Complex
  4. {
  5. public:
  6. Complex( ){real=0;imag=0;}
  7. Complex(double r,double i){real=r;imag=i;}
  8. operator double( ) {return real;} //類型轉換函數
  9. private:
  10. double real;
  11. double imag;
  12. };
  13. int main( )
  14. {
  15. Complex c1(3,4),c2(5,-10),c3;
  16. double d;
  17. d=2.5+c1;//要求將一個double數據與Complex類數據相加
  18. cout<<d<<endl;
  19. return 0;
  20. }

對程序的分析:
1) 如果在Complex類中沒有定義類型轉換函數operator double,程序編譯將出錯。因為不能實現double 型數據與Complex類對象的相加。現在,已定義了成員函數 operator double,就可以利用它將Complex類對象轉換為double型數據。請注意,程序中不必顯式地調用類型轉換函數,它是自動被調用的,即隱式調用。在什么情況下調用類型轉換函數呢?編譯系統在處理表達式 2.5 +cl 時,發現運算符“+”的左側是double型數據,而右側是Complex類對象,又無運算符“+”重載函數,不能直接相加,編譯系統發現有對double的重載函數,因此調用這個函數,返回一個double型數據,然后與2.5相加。

2) 如果在main函數中加一個語句:
    c3=c2;
請問此時編譯系統是把c2按Complex類對象處理呢,還是按double型數據處理?由於賦值號兩側都是同一類的數據,是可以合法進行賦值的,沒有必要把c2轉換為double型數據。

3) 如果在Complex類中聲明了重載運算符“+”函數作為友元函數:
    Complex operator+ (Complex c1,Complex c2)//定義運算符“+”重載函數
    {
        return Complex(c1.real+c2.real, c1.imag+c2.imag);
    }
若在main函數中有語句
    c3=c1+c2;
由於已對運算符“+”重載,使之能用於兩個Complex類對象的相加,因此將c1和c2按Complex類對象處理,相加后賦值給同類對象c3。如果改為
    d=c1+c2; //d為double型變量
將c1與c2兩個類對象相加,得到一個臨時的Complex類對象,由於它不能賦值給double型變量,而又有對double的重載函數,於是調用此函數,把臨時類對象轉換為double數據,然后賦給d。

從前面的介紹可知,對類型的重載和對運算符的重載的概念和方法都是相似的,重載函數都使用關鍵字operator。因此,通常把類型轉換函數也稱為類型轉換運算符函數,由於它也是重載函數,因此也稱為類型轉換運算符重載函數(或稱強制類型轉換運算符重載函數)。

假如程序中需要對一個Complex類對象和一個double型變量進行+,-,*,/等算術運算,以及關系運算和邏輯運算,如果不用類型轉換函數,就要對多種運算符進行重載,以便能進行各種運算。這樣,是十分麻煩的,工作量較大,程序顯得冗長。如果用類型轉換函數對double進行重載(使Complex類對象轉換為double型數據),就不必對各種運算符進行重載,因為Complex類對象可以被自動地轉換為double型數據,而標准類型的數據的運算,是可以使用系統提供的各種運算符的。

[例10.10] 包含轉換構造函數、運算符重載函數和類型轉換函數的程序。先閱讀以下程序,在這個程序中只包含轉換構造函數和運算符重載函數。

  1. #include <iostream>
  2. using namespace std;
  3. class Complex
  4. {
  5. public:
  6. Complex( ){real=0;imag=0;} //默認構造函數
  7. Complex(double r){real=r;imag=0;}//轉換構造函數
  8. Complex(double r,double i){real=r;imag=i;}//實現初始化的構造函數
  9. friend Complex operator + (Complex c1,Complex c2); //重載運算符“+”的友元函數
  10. void display( );
  11. private:
  12. double real;
  13. double imag;
  14. };
  15. Complex operator + (Complex c1,Complex c2)//定義運算符“+”重載函數
  16. {
  17. return Complex(c1.real+c2.real, c1.imag+c2.imag);
  18. }
  19. void Complex::display( )
  20. {
  21. cout<<"("<<real<<","<<imag<<"i)"<<endl;
  22. }
  23. int main( )
  24. {
  25. Complex c1(3,4),c2(5,-10),c3;
  26. c3=c1+2.5; //復數與double數據相加
  27. c3.display( );
  28. return 0;
  29. }

注意,在Visual C++ 6.0環境下運行時,需將第一行改為#include <iostream.h>,並刪去第2行,否則編譯不能通過。

對程序的分析:
1) 如果沒有定義轉換構造函數,則此程序編譯出錯。

2) 現在,在類Complex中定義了轉換構造函數,並具體規定了怎樣構成一個復數。由於已重載了算符“+”,在處理表達式c1+2.5時,編譯系統把它解釋為
    operator+(c1, 2.5)
由於2.5不是Complex類對象,系統先調用轉換構造函數Complex(2.5),建立一個臨時的Complex類對象,其值為(2.5+0i)。上面的函數調用相當於
    operator+(c1, Complex(2.5))
將c1與(2.5+0i) 相加,賦給c3。運行結果為
    (5.5+4i)
3) 如果把“c3=c1+2.5;”改為c3=2.5+c1; 程序可以通過編譯和正常運行。過程與前相同。

從中得到一個重要結論,在已定義了相應的轉換構造函數情況下,將運算符“+”函數重載為友元函數,在進行兩個復數相加時,可以用交換律。

如果運算符函數重載為成員函數,它的第一個參數必須是本類的對象。當第一個操作數不是類對象時,不能將運算符函數重載為成員函數。如果將運算符“+”函數重載為類的成員函數,交換律不適用。

由於這個原因,一般情況下將雙目運算符函數重載為友元函數。單目運算符則多重載為成員函數。

4) 如果一定要將運算符函數重載為成員函數,而第一個操作數又不是類對象時,只有一個辦法能夠解決,再重載一個運算符“+”函數,其第一個參數為double型。當然此函數只能是友元函數,函數原型為
    friend operator+(double, Complex &);
顯然這樣做不太方便,還是將雙目運算符函數重載為友元函數方便些。

5) 在上面程序的基礎上增加類型轉換函數:
    operator double( ){return real;}
此時Complex類的公用部分為:
   public:
   Complex( ){real=0;imag=0;}
   Complex(double r){real=r;imag=0;}  //轉換構造函數
   Complex(double r,double i){real=r;imag=i;}
   operator double( ){return real;}//類型轉換函數
   friend Complex operator+ (Complex c1,Complex c2); //重載運算符“+”
   void display( );
其余部分不變。程序在編譯時出錯,原因是出現二義性。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM