一文帶你探索C++中類型轉(zhuǎn)換的奧秘
const_cast(常量轉(zhuǎn)換)
const_cast(常量轉(zhuǎn)換)是一種類型轉(zhuǎn)換運(yùn)算符,用于修改類型的const或volatile屬性。它通常用于將const變量轉(zhuǎn)換為非常量類型,或者將volatile變量轉(zhuǎn)換為非volatile類型。用法如下:
const_cast<new_type>(expression)
new_type是你要轉(zhuǎn)換成的類型,expression是要被轉(zhuǎn)換的表達(dá)式。
示例
int main() { const int a = 10; // int* pA = &a;//編譯錯(cuò)誤,不能將一個(gè)非常量指針指向一個(gè)常量對(duì)象。 int* pA = const_cast<int*>(&a); *pA = 20; //輸入10 20 cout << "a:" << a << " *pA:" << *pA << endl; }
上面的代碼定義一個(gè) const int
類型的變量 a
,我們想要將其轉(zhuǎn)換為 int 類型。直接用一個(gè)指針pA
指向這個(gè)a
時(shí),由于a
本身是const類型,會(huì)導(dǎo)致編譯錯(cuò)誤。所以我們可以用 const_cast 把它做一個(gè)類型轉(zhuǎn)換,去除 a
的 const 修飾符。然后修改 *pA
的值。
但是大家需要注意,最后的打印輸出是a:10 *pA:20
。
即使你使用 const_cast 去除了指向 a
的指針的常量性, *pA = 20
修改了*pA
的值,實(shí)際上并不會(huì)影響 a
的輸出,這是 C++ 語(yǔ)言的常量性規(guī)則所決定的。因?yàn)樗且粋€(gè)常量。在編譯時(shí),編譯器將 a
的值直接插入到代碼中,而不是通過(guò)指針 pA
訪問(wèn) a。因此無(wú)論如何修改 *pA
,a
的值都保持不變。
const_cast 在某些情況下可以提高代碼的可讀性和減少冗余代碼,但也存在一些缺點(diǎn),例如增加代碼的復(fù)雜度和容易產(chǎn)生歧義。
reinterpret_cast(重新解釋轉(zhuǎn)換)
reinterpret_cast
是一種非常危險(xiǎn)類型轉(zhuǎn)換。它不會(huì)檢查我們所指向的內(nèi)容,也不會(huì)檢查我們這個(gè)類型的本身。它只是做了一個(gè)重新的解釋,我們要在轉(zhuǎn)換的過(guò)程當(dāng)中,保證它轉(zhuǎn)換前和轉(zhuǎn)換后占用的內(nèi)存大小應(yīng)該是一致的。用于在不同類型的指針之間進(jìn)行轉(zhuǎn)換,用法如下:
reinterpret_cast<new_type>(expression)
示例
int Test() { std::cout << "Test function called." << std::endl; return 0; } int main() { //創(chuàng)建一個(gè) FuncPtr 的函數(shù)指針類型。指向沒(méi)有參數(shù)和返回值的函數(shù)。 typedef void(*FuncPtr) (); FuncPtr funcPtr; // funcPtr = &Test; funcPtr = reinterpret_cast<FuncPtr>(&Test); funcPtr(); return 0; }
上述代碼 Test
函數(shù)的返回類型是 int,而 FuncPtr
類型是 void(*)()
,這兩者的返回類型不匹配,因此不能將 Test
函數(shù)指針直接賦給 funcPtr
。可以通過(guò)reinterpret_cast
顯式類型轉(zhuǎn)換來(lái)解決這個(gè)問(wèn)題,funcPtr = reinterpret_cast<FuncPtr>(&Test)
將 Test
函數(shù)的指針轉(zhuǎn)換為 FuncPtr
類型的函數(shù)指針。
reinterpret_cast不進(jìn)行類型檢查非常靈活,可以在不同指針類型之間進(jìn)行轉(zhuǎn)換,包括將指針從對(duì)象類型轉(zhuǎn)換為其他類型,或者在整數(shù)類型和指針之間進(jìn)行轉(zhuǎn)換。但是reinterpret_cast是非常危險(xiǎn)的。因?yàn)樗堰@個(gè)檢查的大部分工作交給程序員自身來(lái)管理的,可能導(dǎo)致轉(zhuǎn)換不合理或不安全。
static_cast(靜態(tài)轉(zhuǎn)換)
static_cast(靜態(tài)轉(zhuǎn)換)可用于對(duì)基本類型進(jìn)行轉(zhuǎn)換,例如int *
轉(zhuǎn)double *
,有繼承關(guān)系的類對(duì)象和類指針之間轉(zhuǎn)換。要注意的是,如果用static_cast
做一個(gè)繼承關(guān)系的轉(zhuǎn)換,安全問(wèn)題需要由程序員自身來(lái)保障。
比如說(shuō)動(dòng)物,它有一個(gè)類叫鴨子,那么鴨子它一定是一種動(dòng)物,所以它有動(dòng)物的行為。但是動(dòng)物未必都有鴨子的行為,所以如果我們把鴨子轉(zhuǎn)換成動(dòng)物,就是一個(gè)叫向上轉(zhuǎn)換的過(guò)程。如果向下轉(zhuǎn)換,那就是把動(dòng)物轉(zhuǎn)換成鴨子。但并不是所有的動(dòng)物都是鴨子,所以這個(gè)地方就存在一些潛在的危險(xiǎn)。如果我們使用static_cast
就不會(huì)發(fā)現(xiàn)這樣的問(wèn)題。但如果我們使用dynamic_cast
,就會(huì)幫我們檢查出來(lái)這種錯(cuò)誤。
示例
class Base { public: Base() : _i(0) {} virtual void T() { cout << "Base:T" << _i << endl; } private: int _i; }; class Derived : public Base { public: Derived() : _j(1) {} virtual void T() { cout << "Derived:T" << _j << endl; } private: int _j; }; void main() { int intValue = 5; double intValue2 = static_cast<double>(intValue); cout << intValue << " " << intValue2 << endl;//5 5 double dValue = 5.6; int dValue2 = static_cast<int>(dValue); cout << dValue << " " << dValue2 << endl;//5.6 5 丟失精度 Base base; Derived derived; Base* pBase; Derived* pDerived; // 父類--》子類 static_cast未做檢查 可能導(dǎo)致運(yùn)行時(shí)錯(cuò)誤 pDerived = static_cast<Derived*>(&base); if (pDerived == NULL) { cout << "unsafe static cast from Base to Derived" << pDerived << endl; } }
上面的static_cast將base轉(zhuǎn)化為Derived*,可能導(dǎo)致運(yùn)行時(shí)錯(cuò)誤。所以在進(jìn)行類型轉(zhuǎn)換時(shí),要注意類型匹配規(guī)則。確保轉(zhuǎn)換是安全的并且符合預(yù)期。例如,在進(jìn)行向下轉(zhuǎn)型時(shí),需要確保子類對(duì)象可以存儲(chǔ)父類對(duì)象。
dynamic_cast (動(dòng)態(tài)轉(zhuǎn)換)
dynamic_cast (動(dòng)態(tài)轉(zhuǎn)換)用于在類的繼承層次之間進(jìn)行類型轉(zhuǎn)換,它既允許向上轉(zhuǎn)型,也允許向下轉(zhuǎn)型。向下轉(zhuǎn)型會(huì)進(jìn)行檢測(cè),如果轉(zhuǎn)換失敗則返回空指針或拋出std::bad_cast異常。用法如下:
dynamic_cast<new_type>(expression)
new_type 和 expression 必須同時(shí)是指針類型或者引用類型。
示例
class Base { public: Base() : _i(0) {} virtual void T() { cout << "Base:T" << _i << endl; } private: int _i; }; class Derived : public Base { public: Derived() : _j(1) {} virtual void T() { cout << "Derived:T" << _j << endl; } private: int _j; }; void main() { Base base; Derived derived; Base* pBase; Derived* pDerived; // 父類--》子類 pDerived輸出NULL pDerived = dynamic_cast<Derived*>(&base); if (pDerived == NULL) { cout << "unsafe dynamic cast from Base to Derived" << endl; } }
上述代碼創(chuàng)建了一個(gè)基類 Base
和一個(gè)派生類 Derived
,然后通過(guò)dynamic_cast
,將基類指針Base
轉(zhuǎn)換為派生類指針 pDerived
。,dynamic_cast
返回 NULL
表示轉(zhuǎn)換失敗。
在動(dòng)態(tài)類型轉(zhuǎn)換中,只能將一個(gè)指向派生類對(duì)象的指針轉(zhuǎn)換為基類指針,而不是反過(guò)來(lái)。這是因?yàn)榕缮悓?duì)象包含了基類的部分,但反之并不成立。
如果想安全地將指向基類對(duì)象的指針轉(zhuǎn)換為指向派生類對(duì)象的指針,要確保對(duì)象實(shí)際上是派生類對(duì)象。
總結(jié)
const_cast
用于轉(zhuǎn)換指針或引用,去掉類型的const屬性;
reinterpret_cast
重新解釋類型,既不檢查指向的內(nèi)容,也不檢查指針類型本身;但要求轉(zhuǎn)換前后的類型所占用內(nèi)存大小一致,否則將引發(fā)編譯時(shí)錯(cuò)誤。
static_cast
用于基本類型轉(zhuǎn)換,有繼承關(guān)系類對(duì)象和類指針之間轉(zhuǎn)換,由程序員來(lái)確保轉(zhuǎn)換是安全的,它不會(huì)產(chǎn)生動(dòng)態(tài)轉(zhuǎn)換的類型安全檢查的開(kāi)銷;
dynamic_cast
只能用于含有虛函數(shù)的類,必須用在多態(tài)體系中,用于類層次間的向上和向下轉(zhuǎn)化;向下轉(zhuǎn)化時(shí),如果是非法的對(duì)于指針?lè)祷豊ULL;
到此這篇關(guān)于一文帶你探索C++中類型轉(zhuǎn)換的奧秘的文章就介紹到這了,更多相關(guān)C++類型轉(zhuǎn)換內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語(yǔ)言實(shí)現(xiàn)選擇排序、冒泡排序和快速排序的代碼示例
這篇文章主要介紹了C++中實(shí)現(xiàn)選擇排序、冒泡排序和快速排序的代碼示例,例子帶有執(zhí)行時(shí)間統(tǒng)計(jì)還可以簡(jiǎn)單看一下效率對(duì)比,需要的朋友可以參考下2016-04-04淺談十進(jìn)制小數(shù)和二進(jìn)制小數(shù)之間的轉(zhuǎn)換
下面小編就為大家?guī)?lái)一篇淺談十進(jìn)制小數(shù)和二進(jìn)制小數(shù)之間的轉(zhuǎn)換。小編覺(jué)得挺不錯(cuò)的現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-01-01關(guān)于在MFC中將窗口最小化到托盤實(shí)現(xiàn)原理及操作步驟
最小化的原理:首先要將窗口隱藏,然后在右下角繪制圖標(biāo);恢復(fù)的原理:將窗口顯示,再將托盤中的圖片刪除,接下來(lái)介紹實(shí)現(xiàn)方法,感興趣的朋友可以了解下啊,希望本文對(duì)你有所幫助2013-01-01C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的計(jì)算器
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-02-02C語(yǔ)言實(shí)現(xiàn)電話訂餐管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)電話訂餐管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01C++數(shù)據(jù)結(jié)構(gòu)關(guān)于棧迷宮求解示例
這篇文章主要為大家介紹了C++數(shù)據(jù)結(jié)構(gòu)關(guān)于棧的迷宮求解示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2021-11-11C語(yǔ)言實(shí)現(xiàn)哈希搜索算法及原理詳解
本文主要介紹了C語(yǔ)言實(shí)現(xiàn)哈希搜索算法及原理詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06c++ 一個(gè)二進(jìn)制串轉(zhuǎn)化為整數(shù)的解決方法
以下是將一個(gè)二進(jìn)制串轉(zhuǎn)化為整數(shù)的實(shí)例。需要的朋友參考下2013-05-05