C++轉換建構函式和隱式轉換函式
阿新 • • 發佈:2019-02-03
其實我們已經在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類物件只有在需要時才進行轉換,要根據表示式的上下文來決定。轉換建構函式和型別轉換運算子有一個共同的功能: 當需要的時候,編譯系統會自動呼叫這些函式,建立一個無名的臨時物件(或臨時變數)。