欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

深入講解C++數(shù)據(jù)類型轉(zhuǎn)換的相關(guān)函數(shù)的知識

 更新時間:2015年09月21日 15:19:43   投稿:goldensun  
這篇文章主要介紹了深入講解C++數(shù)據(jù)類型轉(zhuǎn)換的相關(guān)函數(shù)的知識,包括類型轉(zhuǎn)換運算符函數(shù)等內(nèi)容,需要的朋友可以參考下

C++數(shù)據(jù)類型轉(zhuǎn)換以及轉(zhuǎn)換構(gòu)造函數(shù)
標準數(shù)據(jù)類型之間的轉(zhuǎn)換

在C++中,某些不同類型數(shù)據(jù)之間可以自動轉(zhuǎn)換,例如

  int i = 6;
  i = 7.5 + i;


編譯系統(tǒng)對 7.5是作為double型數(shù)處理的,在求解表達式時,先將6轉(zhuǎn)換成double型,然后與7.5相加,得到和為13.5,在向整型變量i賦值時,將13.5轉(zhuǎn)換為整數(shù)13,然后賦給i。這種轉(zhuǎn)換是由C++編譯系統(tǒng)自動完成的,用戶不需干預(yù)。這種轉(zhuǎn)換稱為隱式類型轉(zhuǎn)換。

C++還提供顯式類型轉(zhuǎn)換,程序人員在程序中指定將一種指定的數(shù)據(jù)轉(zhuǎn)換成另一指定的類型,其形式為:

  類型名(數(shù)據(jù))



  int(89.5)


其作用是將89.5轉(zhuǎn)換為整型數(shù)89。

以前我們接觸的是標準類型之間的轉(zhuǎn)換,現(xiàn)在用戶自己定義了類,就提出了一個問題:一個自定義類的對象能否轉(zhuǎn)換成標準類型? 一個類的對象能否轉(zhuǎn)換成另外一個類的對象?譬如,能否將一個復(fù)數(shù)類數(shù)據(jù)轉(zhuǎn)換成整數(shù)或雙精度數(shù)?能否將Date類的對象轉(zhuǎn)換成Time類的對象?

對于標準類型的轉(zhuǎn)換,編譯系統(tǒng)有章可循,知道怎樣進行轉(zhuǎn)換。而對于用戶自己聲明的類型,編譯系統(tǒng)并不知道怎樣進行轉(zhuǎn)換。解決這個問題的關(guān)鍵是讓編譯系統(tǒng)知道怎樣去進行這些轉(zhuǎn)換,需要定義專門的函數(shù)來處理。
轉(zhuǎn)換構(gòu)造函數(shù)

轉(zhuǎn)換構(gòu)造函數(shù)(conversion constructor function) 的作用是將一個其他類型的數(shù)據(jù)轉(zhuǎn)換成一個類的對象。這里回顧一下以前學(xué)習(xí)過的幾種構(gòu)造函數(shù):
1) 默認構(gòu)造函數(shù)。以Complex類為例,函數(shù)原型的形式為:

  Complex( ); //沒有參數(shù)

2) 用于初始化的構(gòu)造函數(shù)。函數(shù)原型的形式為:

  Complex(double r, double i); //形參表列中一般有兩個以上參數(shù)

3) 用于復(fù)制對象的復(fù)制構(gòu)造函數(shù)。函數(shù)原型的形式為:

  Complex (Complex &c); //形參是本類對象的引用

現(xiàn)在介紹一種新的構(gòu)造函數(shù)——轉(zhuǎn)換構(gòu)造函數(shù)。

轉(zhuǎn)換構(gòu)造函數(shù)只有一個形參,如

  Complex(double r) {real=r;imag=0;}


其作用是將double型的參數(shù)r轉(zhuǎn)換成Complex類的對象,將r作為復(fù)數(shù)的實部,虛部為0。用戶可以根據(jù)需要定義轉(zhuǎn)換構(gòu)造函數(shù),在函數(shù)體中告訴編譯系統(tǒng)怎樣去進行轉(zhuǎn)換。

在類體中,可以有轉(zhuǎn)換構(gòu)造函數(shù),也可以沒有轉(zhuǎn)換構(gòu)造函數(shù),視需要而定。以上幾種構(gòu)造函數(shù)可以同時出現(xiàn)在同一個類中,它們是構(gòu)造函數(shù)的重載。編譯系統(tǒng)會根據(jù)建立對象時給出的實參的個數(shù)與類型選擇形參與之匹配的構(gòu)造函數(shù)。

假如在Complex類中定義了上面的構(gòu)造函數(shù),在Complex類的作用域中有以下聲明語句:

  Complex cl(3.5) ; //建立對象cl,由于只有一個參數(shù),調(diào)用轉(zhuǎn)換構(gòu)造函數(shù)


建立Comptex類對象cl,其real(實部)的值為3.5,imag(虛部)的值為0。它的作用就是將double型常數(shù)轉(zhuǎn)換成一個名為cl的Complex類對象。也可以用聲明語句建立一 個無名的Complex類對象。如

  Complex(3.6) ;  //用聲明語句建立一個無名的對象,合法,但無法使用它

可以在一個表達式中使用無名對象,如:

  cl =Complex(3.6);  //假設(shè)cl巳被定義為Complex類對象


建立一個無名的Complex類對象,其值為(3.6+0i),然后將此無名對象的值賦給cl,cl 在賦值后的值是(3.6+0i)。

如果已對運算符“+”進行了重載,使之能進行兩個Complex類對象的相加,若在程序中有以下表達式:

  c = cl +2.5;


編譯出錯,因為不能用運算符“+”將一個Comptex類對象和一個浮點數(shù)相加。可以先將 2.5轉(zhuǎn)換為Complex類無名對象,然后相加:

  c = cl + Complex (2.5);  //合法

請對比Complex(2.5)和int(2.5)。二者形式類似,int(2.5)是強制類型轉(zhuǎn)換,將2.5轉(zhuǎn)換為整數(shù),int()是強制類型轉(zhuǎn)換運算符。可以認為Complex(2.5)的作用也是強制類型 轉(zhuǎn)換,將2.5轉(zhuǎn)換為Complex類對象。

轉(zhuǎn)換構(gòu)造函數(shù)也是一種構(gòu)造函數(shù),它遵循構(gòu)造函數(shù)的一般規(guī)則。通常把有一個參數(shù)的構(gòu)造函數(shù)用作類型轉(zhuǎn)換,所以,稱為轉(zhuǎn)換構(gòu)造函數(shù)。其實,有一個參數(shù)的構(gòu)造函數(shù)也可以不用作類型轉(zhuǎn)換,如

  Complex (double r){ cout<<r; } //這種用法毫無意義,沒有人會這樣用

轉(zhuǎn)換構(gòu)造函數(shù)的函數(shù)體是根據(jù)需要由用戶確定的,務(wù)必使其有實際意義。例如也可 以這樣定義轉(zhuǎn)換構(gòu)造函數(shù):

  Complex(double r){ real =0; imag = r; }


即實部為0,虛部為r。這并不違反語法,但沒有人會這樣做。應(yīng)該符合習(xí)慣,合乎情理。

注意:轉(zhuǎn)換構(gòu)造函數(shù)只能有一個參數(shù)。如果有多個參數(shù),就不是轉(zhuǎn)換構(gòu)造函數(shù)。原因是顯然的,如果有多個參數(shù)的話,究竟是把哪個參數(shù)轉(zhuǎn)換成Complex類的對象呢?

歸納起來,使用轉(zhuǎn)換構(gòu)造函數(shù)將一個指定的數(shù)據(jù)轉(zhuǎn)換為類對象的方法如下:
1) 先聲明一個類。

2) 在這個類中定義一個只有一個參數(shù)的構(gòu)造函數(shù),參數(shù)的類型是需要轉(zhuǎn)換的類型,在函數(shù)體中指定轉(zhuǎn)換的方法。

3) 在該類的作用域內(nèi)可以用以下形式進行類型轉(zhuǎn)換:
    類名(指定類型的數(shù)據(jù))
就可以將指定類型的數(shù)據(jù)轉(zhuǎn)換為此類的對象。
不僅可以將一個標準類型數(shù)據(jù)轉(zhuǎn)換成類對象,也可以將另一個類的對象轉(zhuǎn)換成轉(zhuǎn)換構(gòu)造函數(shù)所在的類對象。如可以將一個學(xué)生類對象轉(zhuǎn)換為教師類對象,可以在Teacher類中寫出下面的轉(zhuǎn)換構(gòu)造函數(shù):

  Teacher(Student& s){ num=s.num;strcpy(name, s.name);sex=s.sex; }


但應(yīng)注意,對象s中的num,name,sex必須是公用成員,否則不能被類外引用。

C++類型轉(zhuǎn)換函數(shù)(類型轉(zhuǎn)換運算符函數(shù))
用轉(zhuǎn)換構(gòu)造函數(shù)可以將一個指定類型的數(shù)據(jù)轉(zhuǎn)換為類的對象。但是不能反過來將一個類的對象轉(zhuǎn)換為一個其他類型的數(shù)據(jù)(例如將一個Complex類對象轉(zhuǎn)換成double類型數(shù)據(jù))。

C++提供類型轉(zhuǎn)換函數(shù)(type conversion function)來解決這個問題。類型轉(zhuǎn)換函數(shù)的作用是將一個類的對象轉(zhuǎn)換成另一類型的數(shù)據(jù)。如果已聲明了一個Complex類,可以在Complex類中這樣定義類型轉(zhuǎn)換函數(shù):

  operator double( )
  {
    return real;
  }


函數(shù)返回double型變量real的值。它的作用是將一個Complex類對象轉(zhuǎn)換為一個double型數(shù)據(jù),其值是Complex類中的數(shù)據(jù)成員real的值。請注意,函數(shù)名是operator double,這點是和運算符重載時的規(guī)律一致的(在定義運算符“+”的重載函數(shù)時,函數(shù)名是operator +)。

類型轉(zhuǎn)換函數(shù)的一般形式為:

  operator 類型名( )
  {
    實現(xiàn)轉(zhuǎn)換的語句
  }


在函數(shù)名前面不能指定函數(shù)類型,函數(shù)沒有參數(shù)。其返回值的類型是由函數(shù)名中指定的類型名來確定的。類型轉(zhuǎn)換函數(shù)只能作為成員函數(shù),因為轉(zhuǎn)換的主體是本類的對象。不能作為友元函數(shù)或普通函數(shù)。

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

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

[例] 使用類型轉(zhuǎn)換函數(shù)的簡單例子。

#include <iostream>
using namespace std;
class Complex
{
public:
  Complex( ){real=0;imag=0;}
  Complex(double r,double i){real=r;imag=i;}
  operator double( ) {return real;} //類型轉(zhuǎn)換函數(shù)
private:
  double real;
  double imag;
};
int main( )
{
  Complex c1(3,4),c2(5,-10),c3;
  double d;
  d=2.5+c1;//要求將一個double數(shù)據(jù)與Complex類數(shù)據(jù)相加
  cout<<d<<endl;
  return 0;
}

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

2) 如果在main函數(shù)中加一個語句:

  c3=c2;


請問此時編譯系統(tǒng)是把c2按Complex類對象處理呢,還是按double型數(shù)據(jù)處理?由于賦值號兩側(cè)都是同一類的數(shù)據(jù),是可以合法進行賦值的,沒有必要把c2轉(zhuǎn)換為double型數(shù)據(jù)。

3) 如果在Complex類中聲明了重載運算符“+”函數(shù)作為友元函數(shù):

  Complex operator+ (Complex c1,Complex c2)//定義運算符“+”重載函數(shù)
  {
    return Complex(c1.real+c2.real, c1.imag+c2.imag);
  }


若在main函數(shù)中有語句

  c3=c1+c2;


由于已對運算符“+”重載,使之能用于兩個Complex類對象的相加,因此將c1和c2按Complex類對象處理,相加后賦值給同類對象c3。如果改為

  d=c1+c2; //d為double型變量


將c1與c2兩個類對象相加,得到一個臨時的Complex類對象,由于它不能賦值給double型變量,而又有對double的重載函數(shù),于是調(diào)用此函數(shù),把臨時類對象轉(zhuǎn)換為double數(shù)據(jù),然后賦給d。

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

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

[例] 包含轉(zhuǎn)換構(gòu)造函數(shù)、運算符重載函數(shù)和類型轉(zhuǎn)換函數(shù)的程序。先閱讀以下程序,在這個程序中只包含轉(zhuǎn)換構(gòu)造函數(shù)和運算符重載函數(shù)。

#include <iostream>
using namespace std;
class Complex
{
public:
  Complex( ){real=0;imag=0;} //默認構(gòu)造函數(shù)
  Complex(double r){real=r;imag=0;}//轉(zhuǎn)換構(gòu)造函數(shù)
  Complex(double r,double i){real=r;imag=i;}//實現(xiàn)初始化的構(gòu)造函數(shù)
  friend Complex operator + (Complex c1,Complex c2); //重載運算符“+”的友元函數(shù)
  void display( );
private:
  double real;
  double imag;
};
Complex operator + (Complex c1,Complex c2)//定義運算符“+”重載函數(shù)
{
  return Complex(c1.real+c2.real, c1.imag+c2.imag);
}
void Complex::display( )
{
  cout<<"("<<real<<","<<imag<<"i)"<<endl;
}
int main( )
{
  Complex c1(3,4),c2(5,-10),c3;
  c3=c1+2.5; //復(fù)數(shù)與double數(shù)據(jù)相加
  c3.display( );
  return 0;
}

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

對程序的分析:
1) 如果沒有定義轉(zhuǎn)換構(gòu)造函數(shù),則此程序編譯出錯。

2) 現(xiàn)在,在類Complex中定義了轉(zhuǎn)換構(gòu)造函數(shù),并具體規(guī)定了怎樣構(gòu)成一個復(fù)數(shù)。由于已重載了算符“+”,在處理表達式c1+2.5時,編譯系統(tǒng)把它解釋為

  operator+(c1, 2.5)

由于2.5不是Complex類對象,系統(tǒng)先調(diào)用轉(zhuǎn)換構(gòu)造函數(shù)Complex(2.5),建立一個臨時的Complex類對象,其值為(2.5+0i)。上面的函數(shù)調(diào)用相當于

  operator+(c1, Complex(2.5))


將c1與(2.5+0i) 相加,賦給c3。運行結(jié)果為

  (5.5+4i)


3) 如果把“c3=c1+2.5;”改為c3=2.5+c1; 程序可以通過編譯和正常運行。過程與前相同。

從中得到一個重要結(jié)論,在已定義了相應(yīng)的轉(zhuǎn)換構(gòu)造函數(shù)情況下,將運算符“+”函數(shù)重載為友元函數(shù),在進行兩個復(fù)數(shù)相加時,可以用交換律。

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

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

4) 如果一定要將運算符函數(shù)重載為成員函數(shù),而第一個操作數(shù)又不是類對象時,只有一個辦法能夠解決,再重載一個運算符“+”函數(shù),其第一個參數(shù)為double型。當然此函數(shù)只能是友元函數(shù),函數(shù)原型為

  friend operator+(double, Complex &);


顯然這樣做不太方便,還是將雙目運算符函數(shù)重載為友元函數(shù)方便些。

5) 在上面程序的基礎(chǔ)上增加類型轉(zhuǎn)換函數(shù):

  operator double( ){return real;}


此時Complex類的公用部分為:

  public:
  Complex( ){real=0;imag=0;}
  Complex(double r){real=r;imag=0;} //轉(zhuǎn)換構(gòu)造函數(shù)
  Complex(double r,double i){real=r;imag=i;}
  operator double( ){return real;}//類型轉(zhuǎn)換函數(shù)
  friend Complex operator+ (Complex c1,Complex c2); //重載運算符“+”
  void display( );

其余部分不變。程序在編譯時出錯,原因是出現(xiàn)二義性。

相關(guān)文章

最新評論