2021個(gè)人網(wǎng)站盈利模式恢復(fù)2345網(wǎng)址導(dǎo)航
強(qiáng)制類(lèi)型轉(zhuǎn)換運(yùn)算符
帶著三個(gè)疑問(wèn)閱讀:
- 出現(xiàn)的背景是什么?
- 何時(shí)使用?
- 如何使用?
MSDN . 強(qiáng)制轉(zhuǎn)換運(yùn)算符
C++中的四種強(qiáng)制類(lèi)型轉(zhuǎn)換符詳解
static_cast
(1) 使用場(chǎng)景
- 在基本數(shù)據(jù)類(lèi)型之間轉(zhuǎn)換,如把 int 轉(zhuǎn)換為 char,這種帶來(lái)安全性問(wèn)題由程序員來(lái)保證;
- 在有類(lèi)型指針與 void * 之間轉(zhuǎn)換;
- 用于類(lèi)層次結(jié)構(gòu)中基類(lèi)和派生類(lèi)之間指針或引用的轉(zhuǎn)換。
- 上行轉(zhuǎn)換(派生類(lèi)---->基類(lèi))是安全的;
- 下行轉(zhuǎn)換(基類(lèi)---->派生類(lèi))由于沒(méi)有動(dòng)態(tài)類(lèi)型檢查,所以是不安全的。
(2) 使用特點(diǎn)
- 主要執(zhí)行非多態(tài)的轉(zhuǎn)換操作,用于代替C中通常的轉(zhuǎn)換操作。
- 隱式轉(zhuǎn)換都建議使用 static_cast 進(jìn)行標(biāo)明和替換。
- 不能使用 static_cast 在有類(lèi)型指針內(nèi)轉(zhuǎn)換。
dynamic_cast
(1) 使用場(chǎng)景
- 用于將一個(gè)父類(lèi)的指針/引用轉(zhuǎn)化為子類(lèi)的指針/引用(下行轉(zhuǎn)換)
(2) 使用特點(diǎn)
- 基類(lèi)必須要有虛函數(shù),因?yàn)?dynamic_cast 是運(yùn)行時(shí)類(lèi)型檢查,需要運(yùn)行時(shí)類(lèi)型信息,而這個(gè)信息是存儲(chǔ)在類(lèi)的虛函數(shù)表中。
- 對(duì)于下行轉(zhuǎn)換,dynamic_cast 是安全的(當(dāng)類(lèi)型不一致時(shí),轉(zhuǎn)換過(guò)來(lái)的是空指針),而 static_cast 是不安全的。
- 對(duì)指針進(jìn)行 dynamic_cast,失敗返回 NULL,成功返回正常 cast 后的對(duì)象指針;對(duì)引用進(jìn)行 dynamic_cast,失敗拋出一個(gè)異常,成功返回正常 cast 后的對(duì)象引用。
const_cast
(1) 使用場(chǎng)景
- 常量指針(或引用)與非常量指針(或引用)之間的轉(zhuǎn)換。
(2) 使用特點(diǎn)
- cosnt_cast 是四種類(lèi)型轉(zhuǎn)換符中唯一可以對(duì)常量進(jìn)行操作的轉(zhuǎn)換符。
- 去除常量性是一個(gè)危險(xiǎn)的動(dòng)作,盡量避免使用。
reinterpret_cast
(1) 使用場(chǎng)景
- 用在任意指針(或引用)類(lèi)型之間的轉(zhuǎn)換。
- 能夠?qū)⒄娃D(zhuǎn)換為指針,也可以把指針轉(zhuǎn)換為整型或數(shù)組。
(2) 使用特點(diǎn)
- reinterpret_cast 是從底層對(duì)數(shù)據(jù)進(jìn)行重新解釋,依賴具體的平臺(tái),可移植性差。不到萬(wàn)不得已,不用使用這個(gè)轉(zhuǎn)換符,高危操作
示例程序
#include <iostream>namespace staticCast{
/*** @brief static_cast的使用場(chǎng)景* 1. 使用static_cast在基本數(shù)據(jù)類(lèi)型之間轉(zhuǎn)換* 2. 使用static_cast在有類(lèi)型指針與void *之間轉(zhuǎn)換* 3. 用于類(lèi)層次結(jié)構(gòu)中基類(lèi)和派生類(lèi)之間指針或引用的轉(zhuǎn)換*/class CBase // 基類(lèi)(父類(lèi))
{};class CDerived : public CBase // 派生類(lèi)(子類(lèi))
{};int useof_static_cast()
{// 1. 使用static_cast在基本數(shù)據(jù)類(lèi)型之間轉(zhuǎn)換float fval = 10.12;int ival = static_cast<int>(fval); // float --> intstd::cout << ival << std::endl; // out: 10// 2. 使用static_cast在有類(lèi)型指針與void *之間轉(zhuǎn)換int *intp = &ival;void *voidp = static_cast<void *>(intp); // int* --> void*// cout << *voidp << endl; // error,voidp的大小未知long *longp = static_cast<long *>(voidp);std::cout << *longp << std::endl; // out: 10// 3. 用于類(lèi)層次結(jié)構(gòu)中基類(lèi)和派生類(lèi)之間指針或引用的轉(zhuǎn)換// 上行轉(zhuǎn)換(派生類(lèi)---->基類(lèi))是安全的CDerived *tCDerived1 = nullptr;CBase *tCBase1 = static_cast<CBase*>(tCDerived1);// 下行轉(zhuǎn)換(基類(lèi)---- > 派生類(lèi))由于沒(méi)有動(dòng)態(tài)類(lèi)型檢查,所以是不安全的CBase *tCBase2 = nullptr;CDerived *tCDerived2 = static_cast<CDerived*>(tCBase2); //不會(huì)報(bào)錯(cuò),但是不安全// 4. 不能使用static_cast在有類(lèi)型指針內(nèi)轉(zhuǎn)換float *floatp = &fval; //10.12的addr//int *intp1 = static_cast<int *>(floatp); // error,不能使用static_cast在有類(lèi)型指針內(nèi)轉(zhuǎn)換std::cout << *floatp << std::endl; // out: 10.12
}
}// namespace staticCastnamespace dynamicCast{/*** @brief dynamic_cast使用* 1. 用于將一個(gè)父類(lèi)的指針/引用轉(zhuǎn)化為子類(lèi)的指針/引用(下行轉(zhuǎn)換)* 2. 當(dāng)某個(gè)成員函數(shù)只在子類(lèi)中存在,父類(lèi)指針指向子類(lèi)對(duì)象。此時(shí)該指針想要使用子類(lèi)的成員函數(shù),需要將父類(lèi)指針轉(zhuǎn)換為子類(lèi)指針*/
class CBase // 基類(lèi)(父類(lèi))
{
public:// dynamic_cast在將父類(lèi)cast到子類(lèi)時(shí),父類(lèi)必須要有虛函數(shù)virtual int test() { return 0; } // 一定要是 virtual
};class CDerived : public CBase // 派生類(lèi)(子類(lèi))
{
public:int test() { return 1; }
};int useof_dynamic_cast()
{CBase *p_CBase = new CBase; // 基類(lèi)對(duì)象指針CDerived *p_CDerived = dynamic_cast<CDerived *>(p_CBase); // 將基類(lèi)對(duì)象指針類(lèi)型轉(zhuǎn)換為派生類(lèi)對(duì)象指針CBase i_CBase; // 創(chuàng)建基類(lèi)對(duì)象CBase &r_CBase = i_CBase; // 基類(lèi)對(duì)象的引用CDerived &r_CDerived = dynamic_cast<CDerived &>(r_CBase); // 將基類(lèi)對(duì)象的引用轉(zhuǎn)換派生類(lèi)對(duì)象的引用
}
} //namespace dynamicCastnamespace constCast
{
/*** @brief const_cast的使用* **/
int useof_const_cast()
{int value = 100;const int *cpi = &value; // 定義一個(gè)常量指針//*cpi = 200; // 不能通過(guò)常量指針修改值// 1. 將常量指針轉(zhuǎn)換為非常量指針,然后可以修改常量指針指向變量的值int *pi = const_cast<int *>(cpi);*pi = 200;// 2. 將非常量指針轉(zhuǎn)換為常量指針const int *cpi2 = const_cast<const int *>(pi); // *cpi2 = 300; //已經(jīng)是常量指針const int value1 = 500;const int &c_value1 = value1; // 定義一個(gè)常量引用// 3. 將常量引用轉(zhuǎn)換為非常量引用int &r_value1 = const_cast<int &>(c_value1);// 4. 將非常量引用轉(zhuǎn)換為常量引用const int &c_value2 = const_cast<const int &>(r_value1);
}
} // namespace constCastnamespace reinterpretCast
{
int useof_reinterpret_cast()
{int value = 100;// 1. 用在任意指針(或引用)類(lèi)型之間的轉(zhuǎn)換double *pd = reinterpret_cast<double *>(&value);std::cout << "*pd = " << *pd << std::endl;// 2. reinterpret_cast能夠?qū)⒅羔樦缔D(zhuǎn)化為整形值int *pv = &value;int pvaddr = reinterpret_cast<int>(pv);std::cout << "pvaddr = " << pvaddr << std::endl;std::cout << "pv = " << pv << std::endl;
}} // namespaceCastint main(int argc, char* argv[])
{staticCast::useof_static_cast();dynamicCast::useof_dynamic_cast();constCast::useof_const_cast();reinterpretCast::useof_reinterpret_cast();
}