c++類的隱式轉(zhuǎn)換與強制轉(zhuǎn)換重載詳解
在寫這篇文章之前,讓我們先回顧一下編譯器通過匹配過程確定調(diào)用哪一個函數(shù)的匹配順序:
(1)尋找和使用最符合函數(shù)名和參數(shù)類型(包括返回值)的函數(shù),若找到則調(diào)用;
(2)否則,尋找一個函數(shù)模板,將其實例化產(chǎn)生一個匹配的重載函數(shù),若找到則調(diào)用;
(3)否則,尋找可以通過類型轉(zhuǎn)換進行參數(shù)匹配的重載函數(shù),若找到則調(diào)用它。
如果以上步驟均未找到匹配函數(shù),則這個調(diào)用是錯誤的;如果這個調(diào)用有多于一個的匹配選譯,則調(diào)用匹配出現(xiàn)二義性,也是錯誤的。
類型轉(zhuǎn)換是將一種類型的值映射為另一種類型的值。類型轉(zhuǎn)換實際上包含有自動隱含和強制的兩種。
C語言編譯系統(tǒng)提供的內(nèi)部數(shù)據(jù)類型的自動隱式轉(zhuǎn)換規(guī)則如下:
1.程序在執(zhí)行算術(shù)運算時,低類型可以轉(zhuǎn)換為高類型。
2.在賦值表達式中,右邊表達式的值自動隱式轉(zhuǎn)換為左邊變量的類型,并賦值給它。
3.當在函數(shù)調(diào)用時,將實參值賦給形參,系統(tǒng)隱式地將實參轉(zhuǎn)換為形參的類型后,賦給形參。
4.函數(shù)有返回值時,系統(tǒng)將自動地將返回表達式類型轉(zhuǎn)換為函數(shù)類型后,賦值給調(diào)用函數(shù)。
在以上情況下,系統(tǒng)會進行隱式轉(zhuǎn)換的。當在程序中發(fā)現(xiàn)兩個數(shù)據(jù)類型不相容時,又不能自動完成隱式轉(zhuǎn)換,則將出現(xiàn)編譯錯誤。例如:
int* p = 100;
在這種情況下,編譯程序?qū)箦e,為了消除錯誤,可以進行如下所示的強制類型轉(zhuǎn)換:
int* p = (int *)100;
將整型數(shù)100顯式地轉(zhuǎn)換成指針類型。
構(gòu)造函數(shù)具有類型轉(zhuǎn)換功能
在實際應(yīng)用中,當類定義中提供了單個參數(shù)的構(gòu)造函數(shù)時,該類便提供了一種將其他數(shù)據(jù)類型的數(shù)值或變量轉(zhuǎn)換為用戶所定義數(shù)據(jù)類型的方法。因此,可以說單個參數(shù)的構(gòu)造函數(shù)提供了數(shù)據(jù)轉(zhuǎn)換的功能。下面通過一個例子進一步說明單參數(shù)構(gòu)造函數(shù)的類型轉(zhuǎn)換功能。
#include
classA
{
public:
A(){ m=0; }
A(doublei) { m=i; }
voidprint() { cout<<M<
private:
doublem;
};
voidmain()
{
Aa(5);
a=10; //a與10是不同的數(shù)據(jù)類型
a.print();
}
程序的輸出結(jié)果為:
10
在該程序中,賦值語句a=10;中,賦值號兩邊數(shù)值10和對象a是兩上不相容的數(shù)據(jù)類型,可是它卻能順利通過編譯程序,并且輸出顯示正確結(jié)果,其主要原因是得益于單參數(shù)的構(gòu)造函數(shù)。編譯系統(tǒng)選通過標準數(shù)據(jù)類型轉(zhuǎn)換,將整型數(shù)值10轉(zhuǎn)換成double型,然后,再通過類中定義的單參數(shù)構(gòu)造函數(shù)將double型數(shù)值轉(zhuǎn)換為A類類型,最后把它賦值給a。這些轉(zhuǎn)換都是自動隱式完成的。
關(guān)于上面的程序,補充一點:
Aa = 10;
和
Aa;
a= 10;
兩者是不同的,前者對a進行初使化,編譯器會嘗試將10隱式轉(zhuǎn)換為A類型,這樣將引起a的A(doublei)構(gòu)造函數(shù)直接被調(diào)用。
后者屬于賦值語句,編譯器將建立一個臨時對象,并將10隱式轉(zhuǎn)換為A類型。如果我們顯示調(diào)用
(A)10;
這也將建立一個臨時對象,引起A的構(gòu)造函數(shù)被調(diào)用。
還有一點要注意,編譯器只會進行一次隱式轉(zhuǎn)換(C時刻庫的內(nèi)置類型如intshort char等)除外,下面的語句說明了這點:
m_rst->GetFields()->GetItem(nCol)->Value= (_bstr_t)sValue;
上面Value是COM的變體類型,“Value=”將引起operator= (_bstr_t)被調(diào)用。如果上面省略(_bstr_t),編譯器將發(fā)生錯誤,因為沒有operator= (char*)這樣的重載,編譯器不會為我們進行兩次以上的隱式轉(zhuǎn)換。
在函數(shù)調(diào)用過程中,運算符重載和構(gòu)造也是一個函數(shù)調(diào)用,如果匹配的函數(shù)如無二義性,那么將可以產(chǎn)生一次隱式轉(zhuǎn)換。如果上句的Value變體類只有一個operate= (_bstr_t),那么既使這樣寫->Value= sValue; 編譯器也會試圖將sValue隱式轉(zhuǎn)換為_bstr_t類型。
還有一種情況
classA
{
inta;
public:
A(){ };
A(int_a) { a = _a; };
Operatorint() { return a; }
}
有如下調(diào)用:
Aa(10);
Aa2 = (int)(int)a; //只相當于Aa2 = (int)a; 因為第一個就近已經(jīng)轉(zhuǎn)成了int,第二//個就不用再轉(zhuǎn)了
比較有意思吧,A類既有將int隱式轉(zhuǎn)換A的構(gòu)造,也有int()轉(zhuǎn)換函數(shù)供強制轉(zhuǎn)換,(int)(int)a將以就近原則的方式進行。如果就近轉(zhuǎn)換失敗,編譯器將報錯。比如:
classB
{
};
Aa2 = (B)a;
或
Aa2 = (B)10;
編譯器報這樣的錯誤:"errorC2440: “類型轉(zhuǎn)換”:無法從“int”轉(zhuǎn)換為“B”"
可知,我們自己編寫的構(gòu)造和轉(zhuǎn)換函數(shù)多么重要。
轉(zhuǎn)換函數(shù)
轉(zhuǎn)換函數(shù)又稱類型強制轉(zhuǎn)換成員函數(shù),它是類中的一個非靜態(tài)成員函數(shù)。它的定義格式如下:
class<類型說明符1>
{
public:
operator<類型說明符2>();
…
}
這個轉(zhuǎn)換函數(shù)定義了由<類型說明符1>到<類型說明符2>之間的映射關(guān)系??梢?,轉(zhuǎn)換函數(shù)是用來將一種類型的數(shù)據(jù)轉(zhuǎn)換成為另一種類型。下面通過一個例子說明轉(zhuǎn)換函數(shù)的功能。
#include
classRational
{
public:
Rational(intd, int n)
{
den= d;
num= n;
}
operatordouble();//類型轉(zhuǎn)換函數(shù)
private:
intden, num;
};
Rational::operatordouble()
{
returndouble(den)/double(num);
}
voidmain()
{
Rationalr(5, 8);
doubled = 4.7;
d+= r; //這句將調(diào)用隱式轉(zhuǎn)換,相當于d= (double)r;
cout<<d<<ENDL;
}
程序輸出結(jié)果:
5.325
由程序可知,d是一個double型數(shù)值,r是Rational類的對象,這兩個不同類型的數(shù)據(jù)進行加法之所以能夠進行是得益于轉(zhuǎn)換函數(shù)operatordouble()。為使上述加法能夠進行,編譯系統(tǒng)先檢查類Rational的說明,看是否存在在下轉(zhuǎn)換函數(shù)能夠?qū)ational類型的操作數(shù)轉(zhuǎn)換為double類型的操作數(shù)。由于Rational類中說明了轉(zhuǎn)換函數(shù)operatordouble(),它可以在程序運行時進行上述類型轉(zhuǎn)換,因此,該程序中實現(xiàn)了d=r;的操作。
定義轉(zhuǎn)換函數(shù)時應(yīng)注意如下幾點:
(1)轉(zhuǎn)換函數(shù)是用戶定義的成員函數(shù),但它要是非靜態(tài)的。
(2)轉(zhuǎn)換函數(shù)的不可以有返回值。(意思是聲明中不可以有返回值)
(3)轉(zhuǎn)換函數(shù)也不帶任何參數(shù)。
(4)轉(zhuǎn)換函數(shù)函數(shù)還不能定義為友元函數(shù)。
轉(zhuǎn)換函數(shù)的名稱是類型轉(zhuǎn)換的目標類型,因此,不必再為它指定返回值類型;轉(zhuǎn)換函數(shù)是被用于本類型的數(shù)值或變量轉(zhuǎn)換為其他的類型,也不必帶參數(shù)。
類中的構(gòu)造函數(shù)完成其他類型到類類型的轉(zhuǎn)換,而重載強制轉(zhuǎn)換完成類類型到其他類型的轉(zhuǎn)換。
相關(guān)文章
C語言用循環(huán)單鏈表實現(xiàn)約瑟夫環(huán)
這篇文章主要為大家詳細介紹了C語言用循環(huán)單鏈表實現(xiàn)約瑟夫環(huán),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-10-10Qt數(shù)據(jù)庫應(yīng)用之實現(xiàn)數(shù)據(jù)打印到紙張
關(guān)于Qt打印內(nèi)容到紙張,網(wǎng)上的辦法非常多,比如有些直接用painter繪制,逐步控制分頁打印。本文介紹的方法則是將內(nèi)容作為html設(shè)置到文檔對象,再調(diào)用文檔對象的print方法傳入QPrinter對象打印,感興趣的同學可以了解一下2022-01-01