C++中4種類(lèi)型轉(zhuǎn)換的方法分享
1. C語(yǔ)言中的類(lèi)型轉(zhuǎn)換
在C語(yǔ)言中,如果賦值運(yùn)算符左右兩側(cè)類(lèi)型不同,或者形參與實(shí)參類(lèi)型不匹配,或者返回值類(lèi)型與接收返回值類(lèi)型不一致時(shí),就需要發(fā)生類(lèi)型轉(zhuǎn)化,C語(yǔ)言中總共有兩種形式的類(lèi)型轉(zhuǎn)換:隱式類(lèi)型轉(zhuǎn)換和顯式類(lèi)型轉(zhuǎn)換。
1. 隱式類(lèi)型轉(zhuǎn)化:編譯器在編譯階段自動(dòng)進(jìn)行,能轉(zhuǎn)就轉(zhuǎn),不能轉(zhuǎn)就編譯失敗
2. 顯式類(lèi)型轉(zhuǎn)化:需要用戶(hù)自己處理
void Test()
{
int i = 1;
// 隱式類(lèi)型轉(zhuǎn)換
double d = i;
printf("%d, %.2f\n", i, d);
int* p = &i;
// 顯示的強(qiáng)制類(lèi)型轉(zhuǎn)換
int address = (int)p;
printf("%x, %d\n", p, address);
}
缺陷:
轉(zhuǎn)換的可視性比較差,所有的轉(zhuǎn)換形式都是以一種相同形式書(shū)寫(xiě),難以跟蹤錯(cuò)誤的轉(zhuǎn)換
2. 為什么C++需要四種類(lèi)型轉(zhuǎn)換
C風(fēng)格的轉(zhuǎn)換格式很簡(jiǎn)單,但是有不少缺點(diǎn)的:
1. 隱式類(lèi)型轉(zhuǎn)化有些情況下可能會(huì)出問(wèn)題:比如數(shù)據(jù)精度丟失
2. 顯式類(lèi)型轉(zhuǎn)換將所有情況混合在一起,代碼不夠清晰
因此C++提出了自己的類(lèi)型轉(zhuǎn)化風(fēng)格,注意因?yàn)镃++要兼容C語(yǔ)言,所以C++中還可以使用C語(yǔ)言的轉(zhuǎn)化風(fēng)格。
3. C++強(qiáng)制類(lèi)型轉(zhuǎn)換
標(biāo)準(zhǔn)C++為了加強(qiáng)類(lèi)型轉(zhuǎn)換的可視性,引入了四種命名的強(qiáng)制類(lèi)型轉(zhuǎn)換操作符:
static_cast、reinterpret_cast、const_cast、dynamic_cast
3.1 static_cast
static_cast用于非多態(tài)類(lèi)型的轉(zhuǎn)換(靜態(tài)轉(zhuǎn)換),編譯器隱式執(zhí)行的任何類(lèi)型轉(zhuǎn)換都可用static_cast,但它不能用于兩個(gè)不相關(guān)的類(lèi)型進(jìn)行轉(zhuǎn)換
int main()
{
double d = 12.34;
int a = static_cast<int>(d);
cout << a << endl;
return 0;
}
3.2 reinterpret_cast
reinterpret_cast操作符通常為操作數(shù)的位模式提供較低層次的重新解釋?zhuān)糜趯⒁环N類(lèi)型轉(zhuǎn)換為另一種不同的類(lèi)型
int main()
{
double d = 12.34;
int a = static_cast<int>(d);
cout << a << endl;
// 這里使用static_cast會(huì)報(bào)錯(cuò),應(yīng)該使用reinterpret_cast
//int *p = static_cast<int*>(a);
int* p = reinterpret_cast<int*>(a);
return 0;
}
3.3 const_cast
const_cast最常用的用途就是刪除變量的const屬性,方便賦值
void Test()
{
//volatile const int a = 2; //保持內(nèi)存的可見(jiàn)性
const int a = 2;
int* p = const_cast<int*>(&a);
*p = 3;
//因?yàn)閍是const類(lèi)型的變量,所以編譯器進(jìn)行優(yōu)化直接將a值的內(nèi)容放到寄存器中
//用的時(shí)候不會(huì)從內(nèi)存中取,所以a的值是2
//防止編譯的優(yōu)化,可以使用volatile關(guān)鍵字,保持內(nèi)存的可見(jiàn)性
cout << a << endl;
cout << *p << endl;
}
3.4 dynamic_cast
dynamic_cast用于將一個(gè)父類(lèi)對(duì)象的指針/引用轉(zhuǎn)換為子類(lèi)對(duì)象的指針或引用(動(dòng)態(tài)轉(zhuǎn)換)
向上轉(zhuǎn)型:子類(lèi)對(duì)象指針/引用->父類(lèi)指針/引用(不需要轉(zhuǎn)換,賦值兼容規(guī)則)
向下轉(zhuǎn)型:父類(lèi)對(duì)象指針/引用->子類(lèi)指針/引用(用dynamic_cast轉(zhuǎn)型是安全的)
注意:
1. dynamic_cast只能用于父類(lèi)含有虛函數(shù)的類(lèi)
2. dynamic_cast會(huì)先檢查是否能轉(zhuǎn)換成功,能成功則轉(zhuǎn)換,不能則返回0
class A
{
public:
virtual void f() {}
int _a = 0;
};
class B : public A
{
public:
int _b = 0;
};
void fun(A* pa)
{
//直接轉(zhuǎn)換是不安全的可能會(huì)存在越界訪問(wèn)的情況:
//父類(lèi)對(duì)象的指針或引用會(huì)給給子類(lèi)的指針或引用訪問(wèn)子類(lèi)的屬性就會(huì)存在越界訪問(wèn)
B* bptr = (B*)pa;
bptr->_a++;
bptr->_b++;
cout << bptr->_a << endl;
cout << bptr->_b << endl;
}
int main()
{
A a;
B b;
fun(&a);
fun(&b);
return 0;
}運(yùn)行截圖:

解決方案:在類(lèi)型轉(zhuǎn)換的時(shí)候使用用dynamic_cast,如果是父類(lèi)對(duì)象的指針或引用給給子類(lèi)對(duì)象的指針或引用時(shí)則轉(zhuǎn)換不成功。
class A
{
public:
virtual void f() {}
int _a = 0;
};
class B : public A
{
public:
int _b = 0;
};
void fun(A* pa)
{
//dynamic_cast轉(zhuǎn)換時(shí),當(dāng)父類(lèi)對(duì)象的指針或引用給給子類(lèi)的指針或引用是返回0
B* bptr = dynamic_cast<B*>(pa);
if (bptr)
{
bptr->_a++;
bptr->_b++;
cout << bptr->_a << endl;
cout << bptr->_b << endl;
}
}
int main()
{
A a;
B b;
fun(&a);
fun(&b);
return 0;
}運(yùn)行截圖:

注意
強(qiáng)制類(lèi)型轉(zhuǎn)換關(guān)閉或掛起了正常的類(lèi)型檢查,每次使用強(qiáng)制類(lèi)型轉(zhuǎn)換前,程序員應(yīng)該仔細(xì)考慮是否還有其他不同的方法達(dá)到同一目的,如果非強(qiáng)制類(lèi)型轉(zhuǎn)換不可,則應(yīng)限制強(qiáng)制轉(zhuǎn)換值的作用域,以減少發(fā)生錯(cuò)誤的機(jī)會(huì)。強(qiáng)烈建議:避免使用強(qiáng)制類(lèi)型轉(zhuǎn)換
到此這篇關(guān)于C++中4種類(lèi)型轉(zhuǎn)換的方法分享的文章就介紹到這了,更多相關(guān)C++類(lèi)型轉(zhuǎn)換內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語(yǔ)言詳細(xì)講解通過(guò)遞歸實(shí)現(xiàn)掃雷的展開(kāi)
windows自帶的游戲《掃雷》是陪伴了無(wú)數(shù)人的經(jīng)典游戲,本文將利用C語(yǔ)言實(shí)現(xiàn)這一經(jīng)典的游戲,文中的示例代碼講解詳細(xì),感興趣的可以學(xué)習(xí)一下2022-05-05
C++11新特性之四種類(lèi)型轉(zhuǎn)換cast說(shuō)明
類(lèi)型轉(zhuǎn)換是項(xiàng)目中常使用的一種語(yǔ)法規(guī)則,幾乎每個(gè)編程語(yǔ)言都不可避免的涉及到這方面,下面這篇文章主要給大家介紹了關(guān)于C++11新特性之四種類(lèi)型轉(zhuǎn)換cast說(shuō)明的相關(guān)資料,需要的朋友可以參考下2023-02-02
OpenCV實(shí)現(xiàn)輪廓檢測(cè)與繪制
這篇文章主要為大家詳細(xì)介紹了OpenCV實(shí)現(xiàn)輪廓檢測(cè)與繪制,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-06-06
C++的靜態(tài)成員變量和靜態(tài)成員函數(shù)詳解
這篇文章主要為大家介紹了C++的靜態(tài)成員變量和靜態(tài)成員函數(shù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2021-12-12
VisualStudio2022提交git代碼的方法實(shí)現(xiàn)
本文主要介紹了VisualStudio2022提交git代碼的方法實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07
C++初階之list的模擬實(shí)現(xiàn)過(guò)程詳解
在C++中我們經(jīng)常使用STL,那個(gè)在那些我們常用的數(shù)據(jù)結(jié)構(gòu)vector,list的背后,又是如何實(shí)現(xiàn)的呢?這篇文章主要給大家介紹了關(guān)于C++初階之list的模擬實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下2021-08-08

