C++四種case的詳細(xì)介紹小結(jié)
在C++中,我們經(jīng)常使用到類(lèi)型的轉(zhuǎn)換,像把一個(gè)int類(lèi)型轉(zhuǎn)換成char類(lèi)型,一個(gè)int類(lèi)型轉(zhuǎn)換成double類(lèi)型,這些轉(zhuǎn)換屬于隱式類(lèi)型轉(zhuǎn)換。而今天我們要來(lái)講的是顯式類(lèi)型轉(zhuǎn)換。C++提供了四種顯式類(lèi)型轉(zhuǎn)換,分別是:static_cast、dynamic_cast、const_case、reinterpret_case。
一、static_case
static_case的定義為:
static_case<type_name>(expression)
type_name是轉(zhuǎn)換的類(lèi)型,expression是被轉(zhuǎn)換的對(duì)象或者表達(dá)式。
static_case一般用于隱式轉(zhuǎn)換,當(dāng)type_name和express至少有一方可以隱式轉(zhuǎn)換時(shí),則可以用static進(jìn)行強(qiáng)制類(lèi)型轉(zhuǎn)換??梢杂糜诔R?jiàn)的int、float、double等類(lèi)型轉(zhuǎn)換;轉(zhuǎn)換成功返回true,否則返回false(相當(dāng)于C語(yǔ)言中的強(qiáng)制類(lèi)型轉(zhuǎn)換)。
1、基本數(shù)據(jù)類(lèi)型轉(zhuǎn)換
double serven_double_1 = 1.2; std::cout<<serven_double_1<<std::endl; int serven_int_1 = static_cast<int>(serven_double_1); std::cout<<serven_int_1<<std::endl; double serven_double_2 = static_cast<double>(serven_int_1); std::cout<<serven_double_2<<std::endl;
運(yùn)行結(jié)果:基本類(lèi)型的轉(zhuǎn)換,可以看到double類(lèi)型轉(zhuǎn)換成int類(lèi)型后丟失了精度,這一點(diǎn)跟reinterpret_case不一樣,reinterpret_case是底層二進(jìn)制的強(qiáng)制拷貝和語(yǔ)義轉(zhuǎn)換,所以不會(huì)丟失精度,后面會(huì)講到。
2、指針和void指針的轉(zhuǎn)換
int* serven_int_2 = new int(2); void * serven_void_1 = static_cast<void*>(serven_int_2); int *serven_int_3 = static_cast<int*>(serven_void_1); *serven_int_2 = 6; std::cout<<*serven_int_2<<std::endl; std::cout<<*serven_int_3<<std::endl; std::cout<<serven_void_1<<std::endl; std::cout<<serven_int_2<<std::endl; std::cout<<serven_int_3<<std::endl;
運(yùn)行結(jié)果:void指針和其他類(lèi)型的指針進(jìn)行轉(zhuǎn)化的時(shí)候,他們都是指向同一個(gè)地址。
3、父類(lèi)和子類(lèi)之間的轉(zhuǎn)換
class SERVEN_PARENT{ public: SERVEN_PARENT(){} void Function(){ std::cout<<"PARENT"<<std::endl; } }; class SERVEN_CHILD : public SERVEN_PARENT{ public: SERVEN_CHILD(){} void Function(){ std::cout<<"CHILD"<<std::endl; } }; void main(){ SERVEN_PARENT* ser_par = new SERVEN_PARENT(); ser_par->Function(); SERVEN_CHILD* ser_chi = static_cast<SERVEN_CHILD*>(ser_par); ser_chi->Function(); }
運(yùn)行結(jié)果:在main函數(shù)第二行中定義了一個(gè)ser_chi,是一個(gè)派生類(lèi)對(duì)象,然后強(qiáng)制將基類(lèi)對(duì)象轉(zhuǎn)換成子類(lèi),這種叫做下行轉(zhuǎn)換,轉(zhuǎn)換后打印的結(jié)果是子類(lèi)的Function,使用static_case來(lái)進(jìn)行向下轉(zhuǎn)換是不安全的,因?yàn)楫?dāng)子類(lèi)中定義了基類(lèi)沒(méi)有的變量,并且在Function函數(shù)中使用了這個(gè)變量,那么程序?qū)?huì)報(bào)錯(cuò)。
下面我們來(lái)看一下static_case不安全的例子:
class SERVEN_PARENT{ public: SERVEN_PARENT(){} void Function(){ std::cout<<"PARENT"<<std::endl; } }; class SERVEN_CHILD : public SERVEN_PARENT{ public: SERVEN_CHILD(){} void Function(){ std::cout<<"CHILD"<<std::endl; std::cout<<nums<<std::endl; } private: char nums = 'g'; }; void main(){ SERVEN_PARENT* ser_par = new SERVEN_PARENT(); ser_par->Function(); SERVEN_CHILD* ser_chi = static_cast<SERVEN_CHILD*>(ser_par); ser_chi->Function(); }
運(yùn)行結(jié)果:因?yàn)榕缮?lèi)對(duì)象使用了自己獨(dú)有的變量,所以打印char字符的時(shí)候就出現(xiàn)了亂碼。
二、dynamic_case
dynamic_case的定義為:
dynamic<type_name>(expression)
type_name是轉(zhuǎn)換的類(lèi)型,expression是被轉(zhuǎn)換的對(duì)象或者表達(dá)式。
dynamic一般用于基類(lèi)指向派生類(lèi)時(shí)的強(qiáng)制轉(zhuǎn)換,轉(zhuǎn)換成功返回true,失敗返回false。它不像static_case一樣向下轉(zhuǎn)換不安全,它是安全的。它的安全性體現(xiàn)在RTTI,那什么是RTTI呢?
RTTI是運(yùn)行時(shí)類(lèi)型識(shí)別。程序能夠使用基類(lèi)的指針或引用來(lái)檢查著這些指針或引用所指的對(duì)象的實(shí)際派生類(lèi)型(判斷指針原型)。RTTI提供了兩個(gè)非常有用的操作符:typeid和dynamic_cast。(三個(gè)最主要的東西,dynamic_cast,typeid,type_info)。typeid:typeid函數(shù)(為type_info類(lèi)的友元函數(shù),為什么要這樣呢?目的是防止創(chuàng)建type_info對(duì)象)的主要作用就是讓用戶(hù)知道當(dāng)前的變量是什么類(lèi)型的,它可以返回一個(gè)type_info的引用,可以獲取類(lèi)的名稱(chēng)和編碼typeid重載了type_info中的==和!=可以用于判斷兩個(gè)類(lèi)型是否相等。
dynamic_case和static_case在類(lèi)繼承的區(qū)別就是dynamic_case向下轉(zhuǎn)換是安全的。
三、const_case
const_case的定義為:
const_case<type_name>(expression)
type_name是轉(zhuǎn)換的類(lèi)型,expression是被轉(zhuǎn)換的對(duì)象或者表達(dá)式。
const_case有兩個(gè)功能,分別是去掉const和加上const,一般用于去掉const,修改被const修飾為常量的值。但是修改的這個(gè)值本身不能是const常量,而是被二次引用或者傳參數(shù)時(shí)被引用為const,才能修改,否則修改失敗。同時(shí)type和express兩個(gè)類(lèi)型要一直去掉const,修改成功返回true,否則返回false。
1、加上const
int* serven_int_4 = new int(2); const int* serven_int_5 = const_cast<const int*>(serven_int_4); // 轉(zhuǎn)換為常量指針 *serven_int_4 = 3; //*serven_int_5 = 4; // 不能修改 std::cout<<*serven_int_4<<std::endl; std::cout<<*serven_int_5<<std::endl; std::cout<<serven_int_4<<std::endl; std::cout<<serven_int_5<<std::endl;
2、去掉const
(1)const修飾指針,指針指向一個(gè)類(lèi)對(duì)象(常量指針)
將一個(gè)常量指針轉(zhuǎn)換成非常量指針。
class SERVEN_PARENT{ public: SERVEN_PARENT(){} void Function(){ std::cout<<"PARENT"<<std::endl; } }; class SERVEN_CHILD : public SERVEN_PARENT{ public: SERVEN_CHILD(){} void Function(){ std::cout<<"CHILD"<<std::endl; std::cout<<nums<<std::endl; } private: char nums = 'g'; }; void main(){ SERVEN_PARENT ser_par; const SERVEN_PARENT* pP = &ser_par; SERVEN_PARENT* pP_1 = const_case<SERVEN_PARENT*>(pP); // 強(qiáng)制將pP轉(zhuǎn)換成非const }
(2)const修飾指針指向?qū)ο蟮臄?shù)值(指針常量)
將指針常量轉(zhuǎn)換為非指針常量。
void main(){ SERVEN_PARENT ser_par; SERVEN_PARENT* const pP = &ser_par; SERVEN_PARENT* pP_1 = const_case<SERVEN_PARENT*>(pP); // 強(qiáng)制將pP轉(zhuǎn)換成非const }
(3)const修飾指針指向?qū)ο蟮臄?shù)值并且修飾指針(常量指針常量)
常量指針常量可以被轉(zhuǎn)換為非常量指針常量,也可以轉(zhuǎn)換成指針常量或者常量指針。
void main(){ SERVEN_PARENT ser_par; const SERVEN_PARENT* const pP = &ser_par; SERVEN_PARENT* pP_1 = const_case<SERVEN_PARENT*>(pP); // 強(qiáng)制將pP轉(zhuǎn)換成非const const SERVEN_PARENT* pP_2 = const_case<SERVEN_PARENT*>(pP); // 強(qiáng)制將pP轉(zhuǎn)換成常量指針 SERVEN_PARENT* const pP_2 = const_case<SERVEN_PARENT*>(pP); // 強(qiáng)制將pP轉(zhuǎn)換成指針常量 }
四、reinterpret_case
reinterpret_case的定義為:
reinterpret_case<type_name>(expression)
type_name是轉(zhuǎn)換的類(lèi)型,expression是被轉(zhuǎn)換的對(duì)象或者表達(dá)式。
reinterpret_case是一種比較粗暴的轉(zhuǎn)換方式,并且是最不安全的,為什么說(shuō)它粗暴呢?因?yàn)樗苯尤タ截愖畹讓拥亩M(jìn)制,它的本質(zhì)是編譯器的指令,它的作用是可以把一個(gè)指針轉(zhuǎn)換成一個(gè)整數(shù),也可以把一個(gè)整數(shù)轉(zhuǎn)換成一個(gè)指針?;蛘卟煌?lèi)型的指針相互轉(zhuǎn)換。
double serven_double_2 = 1.20; char* serven_char_1 = reinterpret_cast<char* >(&serven_double_2); double* serven_double_3 = reinterpret_cast<double*>(serven_char_1); std::cout<<*serven_double_3<<std::endl; int* serven_int_6 = reinterpret_cast<int*>(&serven_double_2); double* serven_double_4 = reinterpret_cast<double*>(serven_int_6); std::cout<<*serven_double_3<<std::endl;
運(yùn)行結(jié)果:我們可以看到reinterpret_case將double類(lèi)型轉(zhuǎn)換成int,再轉(zhuǎn)換成double類(lèi)型后精度不會(huì)丟失,而static_case會(huì)丟失。
到此這篇關(guān)于C++四種case的詳細(xì)介紹小結(jié)的文章就介紹到這了,更多相關(guān)C++ case內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解C語(yǔ)言在STM32中的內(nèi)存分配問(wèn)題
這篇文章主要介紹了C語(yǔ)言在STM32中的內(nèi)存分配,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-12-12C++實(shí)現(xiàn)String類(lèi)的方法詳解
在C語(yǔ)言中,沒(méi)有專(zhuān)門(mén)用來(lái)表示字符串的類(lèi)型。雖然C語(yǔ)言為字符串提供了一系列的庫(kù)函數(shù),但這些函數(shù)與字符串這個(gè)類(lèi)型是分開(kāi)的。所以在C++中封裝了一個(gè)string類(lèi),來(lái)幫助我們操作字符串,本文就為大家提供了實(shí)現(xiàn)String類(lèi)的方法,需要的可以參考一下2022-08-08C語(yǔ)言手把手教你實(shí)現(xiàn)貪吃蛇AI(上)
這篇文章主要介紹了C語(yǔ)言手把手教你實(shí)現(xiàn)貪吃蛇AI,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01C/C++實(shí)現(xiàn)日期計(jì)算器的示例代碼
本篇文章主要介紹了C/C++實(shí)現(xiàn)日期計(jì)算器的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-09-09用C語(yǔ)言求解一元二次方程的簡(jiǎn)單實(shí)現(xiàn)
這篇文章主要介紹了用C語(yǔ)言求解一元二次方程的簡(jiǎn)單實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11淺析C++調(diào)用Java的Jar包(帶參數(shù))問(wèn)題
這篇文章主要介紹了C++調(diào)用Java的Jar包(帶參數(shù))問(wèn)題,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-11-11