C 四種型別轉換介紹

2021-07-16 16:11:49 字數 4402 閱讀 9417

本文的內容結合作者 和作者 兩篇文章而來的

1. 隱式型別轉換(而對於隱式變換,就是標準的轉換,在很多時候,不經意間就發生了,比如int型別和float型別相加時,int型別就會被隱式的轉換位float型別,然後再進行相加運算。);

2. 顯式型別轉換。

關於強制型別轉換的問題,很多書都討論過,寫的最詳細的是c++ 之父的《c++的設計和演化》。最好的解決方法就是不要使用c風格的強制型別轉換,而是使用標準c++的型別轉換符:static_cast, dynamic_cast。標準c++中有四個型別轉換符:static_cast、dynamic_cast、reinterpret_cast、和 const_cast。下面對它們一一進行介紹。

static_cast的轉換格式:static_cast< type-id > ( expression )

該運算子把expression轉換為type-id型別,但沒有執行時型別檢查來保證轉換的安全性。它主要有如下幾種用法:

①用於類層次結構中基類和子類之間指標或引用的轉換。

進行上行轉換(把子類的指標或引用轉換成基類表示)是安全的;

進行下行轉換(把基類指標或引用轉換成子類表示)時,由於沒有動態型別檢查,所以是不安全的

②用於基本資料型別之間的轉換。如把int轉換成char,把int轉換成enum。這種轉換的安全性也要開發人員來保證。

③把空指標轉換成目標型別的空指標。

④把任何型別的表示式轉換成void型別。

注意:static_cast不能轉換掉expression的const、volatile、或者__unaligned屬性。

主要用於執行「安全的向下轉型(safe down casting)」,也就是說,要確定乙個物件是否是乙個繼承體系中的乙個特定型別。

dynamic_cast的轉換格式:dynamic_cast< type-id > ( expression )

該運算子把expression轉換成type-id型別的物件。type-id必須是類的指標、類的引用或者void*;如果type-id是類指標型別,那麼expression也必須是乙個指標,如果type-id是乙個引用,那麼expression也必須是乙個引用。

dynamic_cast主要用於類層次間的上行轉換和下行轉換,還可以用於類之間的交叉轉換。

在類層次間進行上行轉換時,dynamic_cast和static_cast的效果是一樣的;在進行下行轉換時,dynamic_cast具有型別檢查的功能,比static_cast**更安全。在多型型別之間的轉換主要使用dynamic_cast,因為型別提供了執行時資訊**。

(1).上行轉換

比如b繼承自a,b轉換為a,進行上行轉換時,是安全的,如下:

[cpp] view plain copy print?在code上檢視**片派生到我的**片

#include 

using

namespace

std;

class a

; class b : public a

; int main()

(2).多重繼承之間的上行轉換:

c繼承自b,b繼承自a,這種多重繼承的關係;但是,關係很明確,使用dynamic_cast進行轉換時,也是很簡單的:

class a  

; class b : public a

; class c : public b

; int main()

而上述的轉換,static_cast和dynamic_cast具有同樣的效果。而這種上行轉換,也被稱為隱式轉換;比如我們在定義變數時經常這麼寫:b *pb = new c;這和上面是乙個道理的,只是多加了乙個dynamic_cast轉換符而已。

(3).轉換成void*

可以將類轉換成void *,例如:

class a  

// ......

};

class b

// ......

};

int main()

但是,在類a和類b中必須包含虛函式,為什麼呢?因為類中存在虛函式,就說明它有想讓基類指標或引用指向派生類物件的情況,此時轉換才有意義;由於執行時型別檢查需要執行時型別資訊,而這個資訊儲存在類的虛函式表中,只有定義了虛函式的類才有虛函式表。

(4).如果expression是type-id的基類,使用dynamic_cast進行轉換時,在執行時就會檢查expression是否真正的指向乙個type-id型別的物件,如果是,則能進行正確的轉換,獲得對應的值;否則返回null,如果是引用,則在執行時就會丟擲異常;例如:

class b  

; };

class d : public b

; };

void main()

這個就是下行轉換,從基類指標轉換到派生類指標。

對於一些複雜的繼承關係來說,使用dynamic_cast進行轉換是存在一些陷阱的;比如,鑽石結構:

d型別可以安全的轉換成b和c型別,但是d型別要是直接轉換成a型別呢?

class a  

; class b : public a

; };

class c : public a

; };

class d : public b, public c

};

int main()

如果進行上面的直接轉,你將會得到乙個null的pa指標;這是因為,b和c都繼承了a,並且都實現了虛函式func,導致在進行轉換時,無法進行抉擇應該向哪個a進行轉換。正確的做法是:

int main()  

這就是我在實現queryinte***ce時,得到iunknown的指標時,使用的是*ppv = static_cast

用法:reinpreter_cast(expression)

type-id必須是乙個指標、引用、算術型別、函式指標或者成員指標。它可以把乙個指標轉換成乙個整數,也可以把乙個整數轉換成乙個指標(先把乙個指標轉換成乙個整數,在把該整數轉換成原型別的指標,還可以得到原先的指標值)。

該運算子的用法比較多。

這個操作符的轉換結果幾乎總是與編譯平台息息相關。所以reinterpret_cast不具移植性。

reinterpret_cast的最常用用途是轉換」函式指標「型別。假設有乙個陣列,儲存的都是函式指標,有特定的型別:

typedef void (*funcptr)();//funcptr是個指標,指向某個函式。

funcptr funcptrarray[10];//funcptrarray是個陣列,內有10個funcptrs。

假設由於某種原因,你希望將以下函式的乙個指標放進funcptrarray中:

int dosomething();

如果沒有轉型,不可能辦到這一點,因為dosomething的型別與funcptrarray所能接受的不同。funcptrarray內各函式指標所指函式的返回值是void,但dosomething的返回值卻是int:

funptrarray[0] = &dosomething;//錯誤!型別不對

使用reinterpret_cast,可以強迫編譯器了解你的意圖。

funcptrarray[0] = reinterpret_cast(&dosomething);

const_cast的轉換格式:const_cast (expression)

該運算子用來修改型別的const或volatile屬性。除了const 或volatile修飾之外, type_id和expression的型別是一樣的。

常量指標被轉化成非常量指標,並且仍然指向原來的物件;常量引用被轉換成非常量引用,並且仍然指向原來的物件;常量物件被轉換成非常量物件。

volatile和const類試。舉如下一例:

#include 

using

namespace

std;

class ca

int m_ia;

};

int main()

c 四種型別轉換

c風格的強制型別轉換 type cast 很簡單,不管什麼型別的轉換統統是 type b type a。c 風格的型別轉換提供了4種型別轉換操作符來應對不同場合的應用。const cast,字面上理解就是去const屬性。static cast,命名上理解是靜態型別轉換。如int轉換成char。dy...

C 四種型別轉換

include include includeusing namespace std static cast 用法 static cast type id expression 該運算子把expression轉換為type id型別,但沒有執行時型別檢查來保證轉換的安全性。它主要有如下幾種用法 用於...

C 四種型別轉換

1 static cast 1.上行轉換,把派生類的指標或引用轉換成基類,此時是安全的 2.下行轉換,把基類的指標或者引用轉換成派生類,因為沒有動態監測,所以是不安全的 3.顯示型別轉換,如int轉float等 4.任意型別空指標轉任意型別空指標 5.任意型別表示式轉為void型別 如下 int a...