深刻講授C++數據類型轉換的相干函數的常識。本站提示廣大學習愛好者:(深刻講授C++數據類型轉換的相干函數的常識)文章只能為提供參考,不一定能成為您想要的結果。以下是深刻講授C++數據類型轉換的相干函數的常識正文
C++數據類型轉換和轉換結構函數
尺度數據類型之間的轉換
在C++中,某些分歧類型數據之間可以主動轉換,例如
int i = 6; i = 7.5 + i;
編譯體系對 7.5是作為double型數處置的,在求解表達式時,先將6轉換成double型,然後與7.5相加,獲得和為13.5,在向整型變量i賦值時,將13.5轉換為整數13,然後賦給i。這類轉換是由C++編譯體系主動完成的,用戶不需干涉。這類轉換稱為隱式類型轉換。
C++還供給顯式類型轉換,法式人員在法式中指定將一種指定的數據轉換成另外一指定的類型,其情勢為:
類型名(數據)
如
int(89.5)
其感化是將89.5轉換為整型數89。
之前我們接觸的是尺度類型之間的轉換,如今用戶本身界說了類,就提出了一個成績:一個自界說類的對象可否轉換成尺度類型? 一個類的對象可否轉換成別的一個類的對象?比方,可否將一個單數類數據轉換成整數或雙精度數?可否將Date類的對象轉換成Time類的對象?
關於尺度類型的轉換,編譯體系有章可循,曉得如何停止轉換。而關於用戶本身聲明的類型,編譯體系其實不曉得如何停止轉換。處理這個成績的症結是讓編譯體系曉得如何去停止這些轉換,須要界說專門的函數來處置。
轉換結構函數
轉換結構函數(conversion constructor function) 的感化是將一個其他類型的數據轉換成一個類的對象。這裡回想一下之前進修過的幾種結構函數:
1) 默許結構函數。以Complex類為例,函數原型的情勢為:
Complex( ); //沒有參數
2) 用於初始化的結構函數。函數原型的情勢為:
Complex(double r, double i); //形參表列中普通有兩個以上參數
3) 用於復制對象的復制結構函數。函數原型的情勢為:
Complex (Complex &c); //形參是本類對象的援用
如今引見一種新的結構函數——轉換結構函數。
轉換結構函數只要一個形參,如
Complex(double r) {real=r;imag=0;}
其感化是將double型的參數r轉換成Complex類的對象,將r作為單數的實部,虛部為0。用戶可以依據須要界說轉換結構函數,在函數體中告知編譯體系如何去停止轉換。
在類體中,可以有轉換結構函數,也能夠沒有轉換結構函數,視須要而定。以上幾種結構函數可以同時湧現在統一個類中,它們是結構函數的重載。編譯體系會依據樹立對象時給出的實參的個數與類型選擇形介入之婚配的結構函數。
假設在Complex類中界說了下面的結構函數,在Complex類的感化域中有以下聲明語句:
Complex cl(3.5) ; //樹立對象cl,因為只要一個參數,挪用轉換結構函數
樹立Comptex類對象cl,其real(實部)的值為3.5,imag(虛部)的值為0。它的感化就是將double型常數轉換成一個名為cl的Complex類對象。也能夠用聲明語句樹立一 個無名的Complex類對象。如
Complex(3.6) ; //用聲明語句樹立一個無名的對象,正當,但沒法應用它
可以在一個表達式中應用無名對象,如:
cl =Complex(3.6); //假定cl巳被界說為Complex類對象
樹立一個無名的Complex類對象,其值為(3.6+0i),然後將此無名對象的值賦給cl,cl 在賦值後的值是(3.6+0i)。
假如已對運算符“+”停止了重載,使之能停止兩個Complex類對象的相加,若在法式中有以下表達式:
c = cl +2.5;
編譯失足,由於不克不及用運算符“+”將一個Comptex類對象和一個浮點數相加。可以先將 2.5轉換為Complex類無名對象,然後相加:
c = cl + Complex (2.5); //正當
請比較Complex(2.5)和int(2.5)。兩者情勢相似,int(2.5)是強迫類型轉換,將2.5轉換為整數,int()是強迫類型轉換運算符。可以以為Complex(2.5)的感化也是強迫類型 轉換,將2.5轉換為Complex類對象。
轉換結構函數也是一種結構函數,它遵守結構函數的普通規矩。平日把有一個參數的結構函數用作類型轉換,所以,稱為轉換結構函數。其實,有一個參數的結構函數也能夠不消作類型轉換,如
Complex (double r){ cout<<r; } //這類用法毫有意義,沒有人會如許用
轉換結構函數的函數體是依據須要由用戶肯定的,務必使其有現實意義。例如也可 以如許界說轉換結構函數:
Complex(double r){ real =0; imag = r; }
即實部為0,虛部為r。這其實不違背語法,但沒有人會如許做。應當相符習氣,符合道理。
留意:轉換結構函數只能有一個參數。假如有多個參數,就不是轉換結構函數。緣由是明顯的,假如有多個參數的話,畢竟是把哪一個參數轉換成Complex類的對象呢?
歸結起來,應用轉換結構函數將一個指定的數據轉換為類對象的辦法以下:
1) 先聲明一個類。
2) 在這個類中界說一個只要一個參數的結構函數,參數的類型是須要轉換的類型,在函數體中指定轉換的辦法。
3) 在該類的感化域內可以用以下情勢停止類型轉換:
類名(指定類型的數據)
便可以將指定類型的數據轉換為此類的對象。
不只可以將一個尺度類型數據轉換成類對象,也能夠將另外一個類的對象轉換成轉換結構函數地點的類對象。如可以將一個先生類對象轉換為教員類對象,可以在Teacher類中寫出上面的轉換結構函數:
Teacher(Student& s){ num=s.num;strcpy(name, s.name);sex=s.sex; }
但應留意,對象s中的num,name,sex必需是公用成員,不然不克不及被類外援用。
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類對象只要在須要時才停止轉換,要依據表達式的高低文來決議。轉換結構函數和類型轉換運算符有一個配合的功效:當須要的時刻,編譯體系會主動挪用這些函數,樹立一個無名的暫時對象(或暫時變量)。
[例] 應用類型轉換函數的簡略例子。
#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;} //類型轉換函數 private: double real; double imag; }; int main( ) { Complex c1(3,4),c2(5,-10),c3; double d; d=2.5+c1;//請求將一個double數據與Complex類數據相加 cout<<d<<endl; return 0; }
對法式的剖析:
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型數據,而尺度類型的數據的運算,是可使用體系供給的各類運算符的。
[例] 包括轉換結構函數、運算符重載函數和類型轉換函數的法式。先浏覽以下法式,在這個法式中只包括轉換結構函數和運算符重載函數。
#include <iostream> using namespace std; class Complex { public: Complex( ){real=0;imag=0;} //默許結構函數 Complex(double r){real=r;imag=0;}//轉換結構函數 Complex(double r,double i){real=r;imag=i;}//完成初始化的結構函數 friend Complex operator + (Complex c1,Complex c2); //重載運算符“+”的友元函數 void display( ); private: double real; double imag; }; Complex operator + (Complex c1,Complex c2)//界說運算符“+”重載函數 { 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; //單數與double數據相加 c3.display( ); return 0; }
留意,在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( );
其他部門不變。法式在編譯時失足,緣由是湧現二義性。