c語言的型別轉換比較自由,但也帶來了一些問題,這些問題大多由程式設計師自行控制和解決。對於龐大的c++語言機制而言,這種簡單粗暴的型別轉換方式顯然是個巨大的負擔,因此c++引入4種型別轉換運算子,更加嚴格的限制允許的型別轉換,使轉換過程更加規範:
dynamic_cast 用於多型型別的轉換
static_cast 用於非多型型別的轉換
const_cast 用於刪除const ,volatile 和 __unaligned 屬性
reinterpret_cast 用於位的簡單重新解釋
其中,const_cast和reinterpret_cast的使用會帶來更大的風險,因此不到萬不得已,不推薦使用。
//將expression轉換為type型別.
dynamic_cast
(expression)
;
注:
1、轉換型別必須是乙個指標、引用或者void*,用於將基類的指標或者引用安全地轉換成派生類的指標或引用;
2、dynamic_cast在執行期間強制轉換,執行時進行型別檢查;
3、不能用於內建型別轉換;
4、用於型別轉換,基類中一定要有虛函式(保證多型),不然會編譯錯誤。(類中存在虛函式,就說明它有想要讓基類指標或引用指向派生類物件的情況,此時轉換才有意義。由於執行時型別檢查需要執行時型別資訊,而這個資訊儲存在類的虛函式表中,只有定義了虛函式的類才有虛函式表)
5、對指標進行dynamic_cast,失敗返回null,成功返回正常cast後的物件指標;對引用進行dynamic_cast,失敗丟擲乙個異常,成功返回正常cast後的物件引用。
#include
using
namespace std;
// 基類
class
base
;virtual
~base()
;};//派生類
class
derived
:public base ;}
;int
main()
else
base =
new base;
if(derived* derived =
dynamic_cast
>
(base)
)else
cin.
get();
return0;
}
輸出結果:
基類指標轉換派生類指標成功第一種情況,先讓基類的指標指向派生類物件,這是一種「向上轉換」(upcasting),可以直接隱式轉換,合乎語法。然後令基類指標「公升級為」派生類指標,原則上,這是一種「向下轉換」(downcasting),需要顯示強制轉換,但指向的記憶體是派生類的,派生類指標指向派生類的記憶體,理論上不存在安全隱患,所以用dynamic_cast進行強轉,沒任何問題。void derived::show()
基類指標轉換派生類指標失敗
第二種情況,令派生類指標指向基類物件,顯然是存在安全隱患,dynamic_cast會返回乙個null指標,告訴開發者轉換失敗了。但這個操作發生在執行時。關於不安全的描述
dynamic_cast和傳統的(type)(expression)強制轉換的最大區別在於提供了執行時的型別檢查,保證了型別安全,使用強制轉換,會跳過編譯器的型別檢查,但可能會造成執行時異常,導致程式直接崩潰
//與dynamic_cast作用類似,將expression轉換為type型別,區別在於,static發生於編譯時,dynamic發生於執行時。
static_cast
(expression)
;
1、用於類層次結構中的基類和派生類之間的指標或引用的轉換,其中「向上轉換」是安全的,向下轉換是不安全的,,但二者均可通過編譯,也就是說開發者要負責強轉的執行時安全性,這一點,不如dynamic_cast安全;
#include
using
namespace std;
class
another
;class
base
;class
derived
:public base
;int
main()
2、用於內建型別的轉換
c語言與自己的內建型別隱式轉換規則的,比如說,算術運算,低型別自動往高型別轉換(如圖),但轉換的精度損失由開發者負責,編譯器往往會提出警告。使用了static_cast運算子之後,等於告訴編譯器,「我知道這裡發生了型別轉換,我會為轉換的安全性負責,你不用管了」,編譯器不會發出編譯警告,除非你型別轉換完全非法(比如 int a = static_cast(「hello world!」); ),static_cast才會報編譯錯誤;
3、把void型別轉換成目標型別的指標
4、把任意型別轉換成void 型別
5、static_cast無法轉換expression的const/volitale/__unaligned屬性(會報編譯時錯誤)。
//彌補了static_cast無法轉換const/volitale的不足,將expression的const/volitale屬性移除,僅限於底層const屬性.
const_cast
(expression)
;
1、頂層const:表示指標變數是const的,比如int *const pointer; 底層const: 表示指標所指向的變數是const的,比如const int *pointer;。理解記憶:所謂底層const就是指我這個變數「底子」就是const,改不了,天生麗質難自棄。反之,則是頂層const。
2、const_cast不能執行其他任何型別轉換,只能用於同型別之間不同const/ volitale屬性的移除。否則會報編譯時錯誤。
3、const_cast通常對指標或引用進行轉換,而無法直接移除內建型別的const/volitale的不足,這種語法直接提供了乙個具有寫許可權的指標或引用,可以通過間接方式修改常量。
通過const_cast
常量a被修改。但是這裡有個有趣的現象,就是,指向a的 指標b被修改了,但是a本身卻還是沒變,從位址上看,指標b確實指向了常量a,但是*b和a卻不一樣,這是為什麼呢?推測可能是編譯器(這裡用的visual studio 2017)對字面型常量的引用,有自己的優化,所以a的值沒有發生更改,但實際上已經改了,比如換種方式——
這時會發現,常量a也能改變了(但仍然無法使用a = 30這樣的賦值語句來改變a)。
//reinterpret_cast 允許將任何指標轉換為任何其他指標型別。 也允許將任何整數型別轉換為任何指標型別以及反向轉換。
reinterpret_cast
(expression)
;
① reinterpret_cast 運算子可用於 char* 到 int* 或 one_class* 到 unrelated_class* 之類的轉換,這本身並不安全,但可以通過編譯;
② reinterpret_cast 的本質作用是重新定義記憶體資料的解釋方式,而不進行任何二進位制轉換。
關於reinrepret_cast的部分使用描述
總結
c++提供了這四種型別強制轉換符,主要作用是應對更高階的語法,以及更複雜的情況,以保證更好的安全性。畢竟c++的高階語法,還是蠻複雜的,如果型別轉換像c語言一樣自由而沒有限制,必然會帶來一連串問題。這種機制,一定程度上限定了型別轉換的「規則」。
但對於比較簡單的型別轉換,大可不必這麼複雜,直接用強制轉換(而不是強制轉換運算子)即可。
C 四大型別轉換
c 是一門強型別語言 相比c 來說c語言是弱型別語言 不同自定義型別之間的轉換必須進行顯式轉換。c 中也有隱式型別轉換,所以關於c 到底是強型別語言還是弱型別語言是乙個比較尷尬的問題。c 中提供了四種轉換操作符來細分顯式型別轉換。因為是操作符,所以他們不屬於任何的namespace,也就不用包含任何...
NoSQL的四大型別
1 鍵值資料庫 應用 內容快取 優點 擴充套件性好 靈活性好 大量寫操作時效能高 缺點 無法儲存結構化資訊 條件查詢效率較低 2 列族資料庫 應用 分布式資料儲存與管理 優點 查詢速度快 可擴充套件性強 容易進行分布式擴充套件 複雜性低 使用者 ebay cassandra instagram ca...
資料庫操作四大型別
資料庫操作四大型別 1資料 查詢 dql 語言 基本構成 select from where 這些語句構成 2資料 操縱 dml 語言 基本構成 insert update delete 3資料 定義 ddl 語言 基本構成 create table view 表的建立 屬性定義 4資料 控制 dc...