1. 程式人生 > >C++轉換建構函式和隱式轉換函式

C++轉換建構函式和隱式轉換函式

         其實我們已經在C/C++中見到過多次標準型別資料間的轉換方式了,這種形式用於在程式中將一種指定的資料轉換成另一指定的型別,也即是強制轉換,比如:int a = int(1.23),其作用是將1.23轉換為整形1。然而對於使用者自定義的類型別,編譯系統並不知道如何進行轉換,所以需要定義專門的函式來告訴編譯系統改如何轉換,這就是轉換建構函式和型別轉換函式! 一、轉換建構函式 轉換建構函式(conversion constructor function) 的作用是將一個其他型別的資料轉換成一個類的物件。         當一個建構函式只有一個引數,而且該引數又不是本類的const引用時,這種建構函式稱為轉換建構函式。
        轉換建構函式是對建構函式的過載。         例如: [cpp]  Complex(double r)    {       real=r;       imag=0;   }           其作用是將double型的引數r轉換成Complex類的物件,將r作為複數的實部,虛部為0。使用者可以根據需要定義轉換建構函式,在函式體中告訴編譯系統怎樣去進行轉換。         那麼如何使用轉換建構函式進行型別轉換呢?我們看如下的例子: [cpp]  // TypeSwitch.cpp : 定義控制檯應用程式的入口點。   //   #include "stdafx.h"   #include <iostream>  
using namespace std;   class Complex   {   public:       Complex():real(0),imag(0){};       Complex(double r, double i):real(r),imag(i){};       Complex(double r):real(r),imag(0){};  // 定義轉換建構函式       void Print(){           cout<<"real = " << real <<" image = "<<imag<<endl;  
    }       Complex& operator+(Complex c){           return Complex(this->real + c.real, this->imag + c.imag);            }   private:       double real;       double imag;   };   int main(int argc, _TCHAR* argv[])   {       Complex c;       c = 1.2;  // 呼叫轉換建構函式將1.2轉換為Complex型別       c.Print();       Complex c1(2.9, 4.2);       Complex c2 = c1 + 3.1; // 呼叫轉換建構函式將3.1轉換為Complex型別       c2.Print();       return 0;   }           不僅可以將一個標準型別資料轉換成類物件,也可以將另一個類的物件轉換成轉換建構函式所在的類物件。如可以將一個學生類物件轉換為教師類物件,可以在Teacher類中寫出下面的轉換建構函式: [cpp]   Teacher(Student& s)   {       num=s.num;       strcpy(name,s.name);       sex=s.sex;   }           使用方法同上!         注意:         1.用轉換建構函式可以將一個指定型別的資料轉換為類的物件。但是不能反過來將一個類的物件轉換為一個其他型別的資料(例如將一個Complex類物件轉換成double型別資料)。         2.如果不想讓轉換建構函式生效,也就是拒絕其它型別通過轉換建構函式轉換為本型別,可以在轉換建構函式前面加上explicit!例如: [cpp]  // TypeSwitch.cpp : 定義控制檯應用程式的入口點。   //   #include "stdafx.h"   #include <iostream>   using namespace std;   class Complex   {   public:       Complex():real(0),imag(0){};       Complex(double r, double i):real(r),imag(i){};       explicit Complex(double r):real(r),imag(0){};  // explicit禁止建構函式的轉換功能       void Print(){           cout<<"real = " << real <<" image = "<<imag<<endl;       }   private:       double real;       double imag;   };   int main(int argc, _TCHAR* argv[])   {       Complex c1(1.2, 2.3), c2;       double d;       d = c1 + 1.1; // 呼叫型別轉換函式將c1轉換為double,編譯出錯!       cout<<d<<endl;       return 0;   }   二、型別轉換函式         用轉換建構函式可以將一個指定型別的資料轉換為類的物件。但是不能反過來將一個類的物件轉換為一個其他型別的資料(例如將一個Complex類物件轉換成double型別資料)。而型別轉換函式就是專門用來解決這個問題的! 型別轉換函式的作用是將一個類的物件轉換成另一型別的資料。         如果已聲明瞭一個Complex類,可以在Complex類中這樣定義型別轉換函式: [cpp]  operator double( )   {        return real;   }           型別轉換函式的一般形式為:         operator 型別名( )         {                實現轉換的語句         } 意事項:         1.在函式名前面不能指定函式型別,函式沒有引數。         2.其返回值的型別是由函式名中指定的型別名來確定的。         3.型別轉換函式只能作為成員函式,因為轉換的主體是本類的物件,不能作為友元函式或普通函式。         4.從函式形式可以看到,它與運算子過載函式相似,都是用關鍵字operator開頭,只是被過載的是型別名。double型別經過過載後,除了原有的含義外,還獲得新的含義(將一個Complex類物件轉換為double型別資料,並指定了轉換方法)。這樣,編譯系統不僅能識別原有的double型資料,而且還會把Complex類物件作為double型資料處理。 [cpp]   // TypeSwitch.cpp : 定義控制檯應用程式的入口點。   //      #include "stdafx.h"   #include <iostream>      using namespace std;      class Complex   {   public:       Complex():real(0),imag(0){};       Complex(double r, double i):real(r),imag(i){};       Complex(double r):real(r),imag(0){};  // 定義轉換建構函式          void Print(){           cout<<"real = " << real <<" image = "<<imag<<endl;       }       operator double(){ // 定義型別轉換函式           return real;       }   private:       double real;       double imag;   };      int main(int argc, _TCHAR* argv[])   {       Complex c1(1.2, 2.3);       double d;       d = c1 + 1.1; // 呼叫型別轉換函式將c1轉換為double       cout<<d<<endl;              return 0;   }           本例中,對於d = c1 + 1.1;先呼叫型別轉換函式將c1轉為double型別,然後在與1.1相加!         那麼程式中的Complex類對具有雙重身份,既是Complex類物件,又可作為double型別資料。Complex類物件只有在需要時才進行轉換,要根據表示式的上下文來決定。轉換建構函式和型別轉換運算子有一個共同的功能: 當需要的時候,編譯系統會自動呼叫這些函式,建立一個無名的臨時物件(或臨時變數)。