c 的隱式轉換和強制轉換 非常有用

2021-06-11 12:25:50 字數 3901 閱讀 8405

在寫這篇文章之前,讓我們先回顧一下編譯器通過匹配過程確定呼叫哪乙個函式的匹配順序: (

1)尋找和使用最符合函式名和引數型別(包括返回值)的函式,若找到則呼叫; (

2)否則,尋找乙個函式模板,將其實例化產生乙個匹配的過載函式,若找到則呼叫; (

3)否則,尋找可以通過型別轉換進行引數匹配的過載函式,若找到則呼叫它。

如果以上步驟均未找到匹配函式,則這個呼叫是錯誤的;如果這個呼叫有多於乙個的匹配選譯,則呼叫匹配出現二義性,也是錯誤的。

型別轉換是將一種型別的值對映為另一種型別的值。型別轉換實際上包含有自動隱含和強制的兩種。

c語言編譯系統提供的內部資料型別的自動隱式轉換規則如下:

1.程式在執行算術運算時,低型別可以轉換為高型別。

2.在賦值表示式中,右邊表示式的值自動隱式轉換為左邊變數的型別,並賦值給它。

3.當在函式呼叫時,將實參值賦給形參,系統隱式地將實參轉換為形參的型別後,賦給形參。

4.函式有返回值時,系統將自動地將返回表示式型別轉換為函式型別後,賦值給呼叫函式。

在以上情況下,系統會進行隱式轉換的。當在程式中發現兩個資料型別不相容時,又不能自動完成隱式轉換,則將出現編譯錯誤。例如:

int* p = 100;

在這種情況下,編譯程式將報錯,為了消除錯誤,可以進行如下所示的強制型別轉換:

int* p = (int *)100;

將整型數

100顯式地轉換成指標型別。

建構函式具有型別轉換功能

在實際應用中,當類定義中提供了單個引數的建構函式時,該類便提供了一種將其他資料型別的數值或變數轉換為使用者所定義資料型別的方法。因此,可以說單個引數的建構函式提供了資料轉換的功能。下面通過乙個例子進一步說明單引數建構函式的型別轉換功能。

#include

classa

a(doublei)

voidprint() ;

voidmain()

程式的輸出結果為:

10在該程式中,賦值語句

a=10;

中,賦值號兩邊數值

10和物件

a是兩上不相容的資料型別,可是它卻能順利通過編譯程式,並且輸出顯示正確結果,其主要原因是得益於單引數的建構函式。編譯系統選通過標準資料型別轉換,

將整型數值

10轉換成

double

型,然後,再通過類中定義的單引數建構函式將

double

型數值轉換為

a類型別

,最後把它賦值給

a。這些轉換都是自動隱式完成的。

關於上面的程式,補充一點:

aa = 10; 和

aa;

a= 10;

兩者是不同的,前者對

a進行初使化,編譯器會嘗試將

10隱式轉換為

a型別,這樣將引起a的

a(doublei)

建構函式直接被呼叫。

後者屬於賦值語句,編譯器將建立乙個臨時物件,並將

10隱式轉換為

a型別。如果我們顯示呼叫

(a)10;

這也將建立乙個臨時物件,引起

a的建構函式被呼叫。

還有一點要注意,編譯器只會進行一次隱式轉換(

c時刻庫的內建型別如

intshort char

等)除外,下面的語句說明了這點:

m_rst->getfields()->getitem(ncol)->value= (_bstr_t)svalue;

上面value

是com

的變體型別,「

value=」

將引起operator= (_bstr_t)

被呼叫。如果上面省略

(_bstr_t)

,編譯器將發生錯誤,因為沒有

operator= (char*)

這樣的過載,

編譯器不會為我們進行兩次以上的隱式轉換

。在函式呼叫過程中,

運算子過載和構造也是乙個函式呼叫,如果匹配的函式如無二義性,那麼將可以產生一次隱式轉換

。如果上句的

value

變體類只有乙個

operate= (_bstr_t)

,那麼既使這樣寫

->value= svalue;

編譯器也會試圖將

svalue

隱式轉換為

_bstr_t

型別。

還有一種情況

classa

; a(int_a) ;

operatorint()

}有如下呼叫:

aa(10);

aa2 = (int)(int)a;  

//只相當於

aa2 = (int)a;

因為第乙個就近已經轉成了

int,第二

//個就不用再轉了

比較有意思吧,

a類既有將

int隱式轉換

a的構造,也有

int()

轉換函式供強制轉換,(

int)

(int)a

將以就近原則的方式進行。

如果就近轉換失敗,編譯器將報錯

。比如:

classb

;aa2 = (b)a; 或

aa2 = (b)10;

編譯器報這樣的錯誤:

"errorc2440: 「

型別轉換」

:無法從「

int」

轉換為「

b」"可知,我們自己編寫的構造和轉換函式多麼重要。

轉換函式

轉換函式又稱型別強制轉換成員函式,它是類中的乙個非靜態成員函式。它的定義格式如下:

class<

型別說明符

1>

這個轉換函式定義了由

<

型別說明符

1>

到<

型別說明符

2>

之間的對映關係。可見,轉換函式是用來將一種型別的資料轉換成為另一種型別。下面通過乙個例子說明轉換函式的功能。

#include

classrational

operatordouble();//

型別轉換函式

private:

intden, num;

};rational::operatordouble()

voidmain()

程式輸出結果:

5.325

由程式可知,

d是乙個

double

型數值,r是

rational

類的物件,這兩個不同型別的資料進行加法之所以能夠進行是得益於轉換函式

operatordouble()

。為使上述加法能夠進行,編譯系統先檢查類

rational

的說明,看是否存在在下轉換函式能夠將

rational

型別的運算元轉換為

double

型別的運算元。由於

rational

類中說明了轉換函式

operatordouble()

,它可以在程式執行時進行上述型別轉換,因此,該程式中實現了

d=r;

的操作。

定義轉換函式時應注意如下幾點:

(1)轉換函式是使用者定義的成員函式,但它要是非靜態的。

(2)轉換函式的不可以有返回值

。(意思是宣告中不可以有返回值)

(3)轉換函式也不帶任何引數。

(4)轉換函式函式還不能定義為友元函式。

轉換函式的名稱是型別轉換的目標型別,因此,不必再為它指定返回值型別;轉換函式是被用於本型別的數值或變數轉換為其他的型別,也不必帶引數。

類中的建構函式完成其他型別到類型別的轉換,而過載強制轉換完成類型別到其他型別的轉換。

js強制轉換和隱式轉換

一 強制轉換 使用string number boolean 函式強制轉換 var str 100 var str1 100 console.log typeof str number console.log typeof str1 string console.log typeof string ...

C強制型別轉換與隱式轉換

如果乙個運算子兩邊的運算數型別不同,先要將其轉換為相同的型別,即較低型別轉換為較高型別,然後再參加運算,轉換規則如下圖所示 圖中橫向箭頭表示必須的轉換,如兩個float型數參加運算,雖然它們型別相同,但仍要先轉成double型再進行運算,結果亦為double型。縱向箭頭表示當運算子兩邊的運算數為不同...

c 中的型別轉換(強制轉換和隱式型別轉換)

在我們學習c語言的時候,就知道強制型別轉換和隱式型別的轉換,但是在型別轉換的過程中,很有可能乙個不注意,容易出問題,這無疑是加大了,程式設計師的工作量,而且還檢查很不好檢查。所以在c 中就對型別的轉換做了一定的限制,但是實際中大多數人,是在學習了c 語言後才學習 c 語言所以就用了 c 語言中的型別...