C 的四種顯示轉換

2021-10-05 21:20:14 字數 3802 閱讀 1790

**: (果凍想)

前言這篇文章總結的是c++中的型別轉換,這些小的知識點,有的時候,自己不是很注意,但是在實際開發中確實經常使用的。俗話說的好,不懂自己寫的**的程式設計師,不是好的程式設計師;如果乙個程式設計師對於自己寫的**都不懂,只是知道一昧的的去使用,終有一天,你會迷失你自己的。

c++中的型別轉換分為兩種:

隱式型別轉換;

顯式型別轉換。

而對於隱式變換,就是標準的轉換,在很多時候,不經意間就發生了,比如int型別和float型別相加時,int型別就會被隱式的轉換位float型別,然後再進行相加運算。而關於隱式轉換不是今天總結的重點,重點是顯式轉換。在標準c++中有四個型別轉換符:static_cast、dynamic_cast、const_cast和reinterpret_cast;下面將對它們一一的進行總結。

static_cast

static_cast的轉換格式:static_cast(expression)

將expression轉換為type-id型別,主要用於非多型型別之間的轉換,不提供執行時的檢查來確保轉換的安全性。主要在以下幾種場合中使用:

1.用於類層次結構中,基類和子類之間指標和引用的轉換;

當進行上行轉換,也就是把子類的指標或引用轉換成父類表示,這種轉換是安全的;

當進行下行轉換,也就是把父類的指標或引用轉換成子類表示,這種轉換是不安全的,也需要程式設計師來保證;

2.用於基本資料型別之間的轉換,如把int轉換成char,把int轉換成enum等等,這種轉換的安全性需要程式設計師來保證;

2.把void指標轉換成目標型別的指標,是及其不安全的;

:static_cast不能轉換掉expression的const、volatile和__unaligned屬性。

dynamic_cast

dynamic_cast的轉換格式:dynamic_cast (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,因為型別提供了執行時資訊。下面我將分別在以下的幾種場合下進行dynamic_cast的使用總結:

1.最簡單的上行轉換

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

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

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

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

3.轉換成void *

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

class

a// ......};

class

b// ......};

intmain()

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

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

```cpp

classb;

};classd:

public b;}

;void

main()

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

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

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

classa;

classb:

public a;}

;classc:

public a;}

;classd:

public b,

public c};

intmain()

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

int

main()

這就是我在實現queryinte***ce時,得到iunknown的指標時,使用的是*ppv = static_cast>(this);而不是ppv = static_cast(this);

對於多重繼承的情況,從派生類往父類的父類進行轉時,需要特別注意;比如有下面這種情況:

現在,你擁有乙個a型別的指標,它指向e例項,如何獲得b型別的指標,指向e例項呢?如果直接進行轉的話,就會出現編譯器出現分歧,不知道是走e->c->b,還是走e->d->b。對於這種情況,我們就必須先將a型別的指標進行下行轉換,獲得e型別的指標,然後,在指定一條正確的路線進行上行轉換。

上面就是對於dynamic_cast轉換的一些細節知識點,特別是對於多重繼承的情況,在實際專案中,很容易出現問題。

const_cast

const_cast的轉換格式:const_cast (expression)

const_cast用來將型別的const、volatile和__unaligned屬性移除。常量指標被轉換成非常量指標,並且仍然指向原來的物件;常量引用被轉換成非常量引用,並且仍然引用原來的物件。看以下的**例子:

#include

using

namespace std;

class

caint m_ia;};

intmain()

注:你不能直接對非指標和非引用的變數使用const_cast操作符去直接移除它的const、volatile和__unaligned屬性。

reinterpret_cast

reinterpret_cast的轉換格式:reinterpret_cast (expression)

允許將任何指標型別轉換為其它的指標型別;聽起來很強大,但是也很不靠譜。它主要用於將一種資料型別從一種型別轉換為另一種型別。它可以將乙個指標轉換成乙個整數,也可以將乙個整數轉換成乙個指標,在實際開發中,先把乙個指標轉換成乙個整數,在把該整數轉換成原型別的指標,還可以得到原來的指標值;特別是開闢了系統全域性的記憶體空間,需要在多個應用程式之間使用時,需要彼此共享,傳遞這個記憶體空間的指標時,就可以將指標轉換成整數值,得到以後,再將整數值轉換成指標,進行對應的操作。

C 中四種顯示型別轉換總結

include usingnamespacestd 四種顯示型別轉換 intmain classfather publicbase father f base ba static cast f reinterpret cast型別轉換 基本型別的指標型別轉換 doublec 12.123 doubl...

c 四種強制轉換

c 同時提供了四種新的強制轉型形式 通常稱為新風格的或 c 風格的強制轉型 const cast expression dynamic cast expression reinterpret cast expression static cast expression 每一種適用於特定的目的 con...

四種C 型別轉換

1 static cast 用法 static cast type id expression 該運算子把expression轉換為type id型別,但沒有執行時型別檢查來保證轉換的安全性。它主要有如下幾種用法 用於類層次結構中基類和子類之間指標或引用的轉換。進行上行轉換 把子類的指標或引用轉換成...