引言
?? 作者簡(jiǎn)介:專注于C/C++高性能程序設(shè)計(jì)和開(kāi)發(fā),理論與代碼實(shí)踐結(jié)合,讓世界沒(méi)有難學(xué)的技術(shù)。包括C/C++、Linux、MySQL、Redis、TCP/IP、協(xié)程、網(wǎng)絡(luò)編程等。
??
??? CSDN實(shí)力新星,社區(qū)專家博主
??
?? 專欄介紹:從零到c++精通的學(xué)習(xí)之路。內(nèi)容包括C++基礎(chǔ)編程、中級(jí)編程、高級(jí)編程;掌握各個(gè)知識(shí)點(diǎn)。
??
?? 專欄地址:C++從零開(kāi)始到精通
??
?? 博客主頁(yè):https://blog.csdn.net/Long_xu
?? 上一篇:【035】C++泛型編程(模板)實(shí)踐:設(shè)計(jì)數(shù)組類模板模仿vector容器
一、類型轉(zhuǎn)換簡(jiǎn)介
標(biāo)準(zhǔn)C++提供了一個(gè)顯式的轉(zhuǎn)換語(yǔ)法,用來(lái)代替C語(yǔ)言風(fēng)格的類型轉(zhuǎn)換。使用C語(yǔ)言風(fēng)格的強(qiáng)制轉(zhuǎn)換可以把想要的任何東西轉(zhuǎn)換成我們需要的類型。
新類型的強(qiáng)制轉(zhuǎn)換可以提供更好的控制強(qiáng)制轉(zhuǎn)換過(guò)程,允許控制各種不同類型的強(qiáng)制轉(zhuǎn)換。
C++風(fēng)格的強(qiáng)制轉(zhuǎn)換的好處:能更清晰的表明它們要干什么。開(kāi)發(fā)者只要看一眼這樣的代碼,就能夠立即知道一個(gè)強(qiáng)制轉(zhuǎn)換目的。
C++中的類型轉(zhuǎn)換允許將一個(gè)數(shù)據(jù)類型轉(zhuǎn)換為另一個(gè)數(shù)據(jù)類型。C++提供了多種類型轉(zhuǎn)換操作符和函數(shù)來(lái)執(zhí)行不同類型之間的轉(zhuǎn)換。
以下是C++中常見(jiàn)的類型轉(zhuǎn)換方式:
-
隱式類型轉(zhuǎn)換(Implicit Type Conversion):也稱為自動(dòng)類型轉(zhuǎn)換,是編譯器隱式地執(zhí)行的類型轉(zhuǎn)換。這種轉(zhuǎn)換是安全的,可以由編譯器自動(dòng)完成,無(wú)需顯式指定。例如,將一個(gè)整數(shù)賦值給一個(gè)浮點(diǎn)數(shù)變量,編譯器會(huì)自動(dòng)將整數(shù)轉(zhuǎn)換為浮點(diǎn)數(shù)。
-
顯式類型轉(zhuǎn)換(Explicit Type Conversion):也稱為強(qiáng)制類型轉(zhuǎn)換,是通過(guò)使用轉(zhuǎn)換操作符或函數(shù)來(lái)顯式指定類型轉(zhuǎn)換的方式。顯式類型轉(zhuǎn)換可能會(huì)導(dǎo)致數(shù)據(jù)丟失或精度損失。C++提供了以下三種顯式類型轉(zhuǎn)換方式:
- 靜態(tài)轉(zhuǎn)換(static_cast):用于基本數(shù)據(jù)類型之間的轉(zhuǎn)換,以及具有繼承關(guān)系的指針和引用之間的轉(zhuǎn)換。
- 動(dòng)態(tài)轉(zhuǎn)換(dynamic_cast):用于具有繼承關(guān)系的類之間的轉(zhuǎn)換,可以在運(yùn)行時(shí)檢查類型轉(zhuǎn)換的有效性。
- 常量轉(zhuǎn)換(const_cast):用于去除指針或引用的常量屬性。
-
重新解釋轉(zhuǎn)換(reinterpret_cast):用于將一個(gè)指針或引用轉(zhuǎn)換為另一個(gè)不相關(guān)類型的指針或引用,這是一種非常危險(xiǎn)的轉(zhuǎn)換,需要謹(jǐn)慎使用。
類型轉(zhuǎn)換應(yīng)該在必要時(shí)使用,并且要確保轉(zhuǎn)換的安全性。錯(cuò)誤的類型轉(zhuǎn)換可能導(dǎo)致數(shù)據(jù)丟失、不可預(yù)料的行為或程序崩潰。所以,在進(jìn)行類型轉(zhuǎn)換時(shí),一定要了解數(shù)據(jù)類型的特點(diǎn),并謹(jǐn)慎選擇適當(dāng)?shù)霓D(zhuǎn)換方式。
二、上行、下行轉(zhuǎn)換的概述
在C++中,上行轉(zhuǎn)換(upcasting)和下行轉(zhuǎn)換(downcasting)是指在繼承關(guān)系中的類型轉(zhuǎn)換。
-
上行轉(zhuǎn)換(Upcasting):將派生類指針或引用轉(zhuǎn)換為基類指針或引用。上行轉(zhuǎn)換是安全的,因?yàn)榕缮悓?duì)象中包含了基類對(duì)象的所有成員。上行轉(zhuǎn)換是隱式的,不需要顯式指定,編譯器會(huì)自動(dòng)完成。例如,如果有一個(gè)基類Animal和一個(gè)派生類Dog,那么可以將Dog對(duì)象的指針或引用賦值給Animal對(duì)象的指針或引用。
-
下行轉(zhuǎn)換(Downcasting):將基類指針或引用轉(zhuǎn)換為派生類指針或引用。下行轉(zhuǎn)換是不安全的,因?yàn)榛悓?duì)象中可能沒(méi)有派生類特有的成員。下行轉(zhuǎn)換必須顯式指定,并且需要使用
dynamic_cast
運(yùn)算符進(jìn)行類型檢查。在運(yùn)行時(shí),dynamic_cast
會(huì)檢查轉(zhuǎn)換是否有效,如果轉(zhuǎn)換無(wú)效,返回空指針(對(duì)于指針)或引發(fā)std::bad_cast
異常(對(duì)于引用)。例如,如果有一個(gè)基類Animal的指針或引用,可以使用dynamic_cast
將其轉(zhuǎn)換為派生類Dog的指針或引用。
下行轉(zhuǎn)換只有在確保基類對(duì)象指向的是派生類對(duì)象時(shí)才能安全進(jìn)行。否則,進(jìn)行下行轉(zhuǎn)換可能會(huì)導(dǎo)致未定義的行為或程序崩潰。因此,在進(jìn)行下行轉(zhuǎn)換時(shí),最好先使用dynamic_cast
進(jìn)行類型檢查,以確保轉(zhuǎn)換的有效性。
三、static_cast 靜態(tài)類型轉(zhuǎn)換
static_cast 用于類層次結(jié)構(gòu)中基類(父類)和派生類(子類)之間指針和引用的轉(zhuǎn)換。它支持:
- 基本類型。
- 上行轉(zhuǎn)換。
- 下行轉(zhuǎn)換。
不支持不相干類型轉(zhuǎn)換。
假設(shè)存在這樣的類:
class Base{
};
class Son:public Base{
};
class Other{
};
(1)支持基本類型。
int num=static_cast<int>(3.1415);// ok
(2)支持上行轉(zhuǎn)換,安全。
Base *p=static_cast<Base *>(new Son);// ok
(3)支持下行轉(zhuǎn)換,不安全。
Son *p=static_cast<Son *>(new Base);// ok
(4)不支持不相關(guān)類型的轉(zhuǎn)換。
Base *p=static_cast<Base *>(new Other);// error
完整示例:
#include <iostream>
using namespace std;
class Base {
};
class Son :public Base {
};
class Other {
};
int main()
{
int num = static_cast<int>(3.1415);// ok
Base *p = static_cast<Base *>(new Son);// ok
Son *p2 = static_cast<Son *>(new Base);// ok
//Base *p = static_cast<Base *>(new Other);// error
return 0;
}
四、dynamic_cast 靜態(tài)類型轉(zhuǎn)換(推薦使用)
dynamic_cast 主要用于類層次間的上行轉(zhuǎn)換和下行轉(zhuǎn)換。一種最安全的類型轉(zhuǎn)換。
假設(shè)存在這樣的類:
class Base{
};
class Son:public Base{
};
class Other{
};
(1)不支持基本類型。
int num=dynamic_cast<int>(3.1415);// error
(2)支持上行轉(zhuǎn)換,安全。
Base *p=dynamic_cast<Base *>(new Son);// ok
(3)不支持下行轉(zhuǎn)換,不安全。
Son *p=dynamic_cast<Son *>(new Base);// error
(4)不支持不相關(guān)類型的轉(zhuǎn)換。
Base *p=dynamic_cast<Base *>(new Other);// error
完整示例:
#include <iostream>
using namespace std;
class Base {
};
class Son :public Base {
};
class Other {
};
int main()
{
int num = dynamic_cast<int>(3.1415);// error
Base *p = dynamic_cast<Base *>(new Son);// ok
Son *p2 = dynamic_cast<Son *>(new Base);// error
Base *p3 = dynamic_cast<Base *>(new Other);// error
return 0;
}
報(bào)錯(cuò)效果:
五、const_cast 常量轉(zhuǎn)換
語(yǔ)法:
const_cast< new-type expression>(...)
返回new-type類型的值。
用途:
- 將const修飾的指針或引用轉(zhuǎn)換成非const。
- 將非const修飾的指針或引用轉(zhuǎn)換成const。
const int *p;
int *p2=const_cast<int *>(p);
const int &ob=10;
int &ob2=const_cast<int &>(ob);
int *p3;
const int *p4=const_cast<int *>(p3);
int ob3=10;
const int &ob4=const_cast<int &>(ob3);
const_cast只能進(jìn)行以下轉(zhuǎn)換。特別是,只有const_cast可用于拋棄(去除)恒常性或波動(dòng)性。
(1)指向同一類型的兩個(gè)可能的多級(jí)指針可以相互轉(zhuǎn)換,而不必考慮每個(gè)級(jí)別上的cv限定符。
(2)任何類型的左值都可以轉(zhuǎn)換為相同類型的左值或右值引用,或多或少受cv限制。同樣,類類型的右值或任何類型的右值都可以轉(zhuǎn)換為或多或少限定cv的右值引用。如果表達(dá)式是一個(gè)全局值,則引用const_cast的結(jié)果指向原始對(duì)象,否則指向物化的臨時(shí)對(duì)象。
(4)同樣的規(guī)則也適用于可能指向數(shù)據(jù)成員的多級(jí)指針,以及可能指向具有已知和未知邊界的數(shù)組的多級(jí)指針(指向限定cv的元素的數(shù)組本身也被認(rèn)為是限定cv的)。
(5)空指針值可以轉(zhuǎn)換為new-type的空指針值。
示例:
#include <iostream>
struct type
{
int i;
type(): i(3) {}
void f(int v) const
{
// this->i = v; // compile error: this is a pointer to const
const_cast<type*>(this)->i = v; // OK as long as the type object isn't const
}
};
int main()
{
int i = 3; // i is not declared const
const int& rci = i;
const_cast<int&>(rci) = 4; // OK: modifies i
std::cout << "i = " << i << '\n';
type t; // if this was const type t, then t.f(4) would be undefined behavior
t.f(4);
std::cout << "type::i = " << t.i << '\n';
const int j = 3; // j is declared const
[[maybe_unused]]
int* pj = const_cast<int*>(&j);
// *pj = 4; // undefined behavior
[[maybe_unused]]
void (type::* pmf)(int) const = &type::f; // pointer to member function
// const_cast<void(type::*)(int)>(pmf); // compile error: const_cast does
// not work on function pointers
}
六、reinterpret_cast 重新解釋轉(zhuǎn)換(最不安全)
不支持基本類型,但是支持基本類型指針,而且其他的基本都支持,所以是最不安全的。
假設(shè)存在這樣的類:
class Base{
};
class Son:public Base{
};
class Other{
};
(1)不支持基本類型,但支持基本類型指針。
int num=reinterpret_cast<int>(3.1415);// error
float *q;
int *p=reinterpret_cast<int *>(q);// ok
(2)支持上行轉(zhuǎn)換。
Base *p=reinterpret_cast<Base *>(new Son);// ok
(3)支持下行轉(zhuǎn)換。
Son *p=reinterpret_cast<Son *>(new Base);// ok
(4)支持不相關(guān)類型的轉(zhuǎn)換。
Base *p=reinterpret_cast<Base *>(new Other);// ok
完整示例:
#include <iostream>
using namespace std;
class Base {
};
class Son :public Base {
};
class Other {
};
int main()
{
int num = reinterpret_cast<int>(3.1415);// error
float q = 3.16f;
float *q2 = &q;
int *num2 = reinterpret_cast<int *>(q2);// ok
Base *p = reinterpret_cast<Base *>(new Son);// ok
Son *p2 = reinterpret_cast<Son *>(new Base);// ok
Base *p3 = reinterpret_cast<Base *>(new Other);// ok
return 0;
}
總結(jié)
- 靜態(tài)類型轉(zhuǎn)換
靜態(tài)類型轉(zhuǎn)換是最常用的類型轉(zhuǎn)換方式,它可以將一種類型的數(shù)據(jù)強(qiáng)制轉(zhuǎn)換為另一種類型,但需要注意的是,這種轉(zhuǎn)換可能會(huì)損失一些信息,因此在進(jìn)行此類轉(zhuǎn)換時(shí)應(yīng)當(dāng)謹(jǐn)慎。
例如:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-526526.html
int a = 10;
double b = static_cast<double>(a);
- 動(dòng)態(tài)類型轉(zhuǎn)換
動(dòng)態(tài)類型轉(zhuǎn)換主要用于多態(tài)類型之間的轉(zhuǎn)換,它可以將基類指針或引用轉(zhuǎn)換為派生類指針或引用。如果進(jìn)行非法的類型轉(zhuǎn)換,動(dòng)態(tài)類型轉(zhuǎn)換會(huì)返回一個(gè)空指針。
例如:
class Base {};
class Derived : public Base {};
Base* base = new Derived;
Derived* derived = dynamic_cast<Derived*>(base);
- 重新解釋類型轉(zhuǎn)換
重新解釋類型轉(zhuǎn)換可以將一個(gè)對(duì)象的二進(jìn)制表示重新解釋為另一種類型的對(duì)象,這種轉(zhuǎn)換通常用于底層編程和特殊的系統(tǒng)級(jí)程序中。
例如:
int a = 100;
float b = reinterpret_cast<float&>(a);
- const_cast轉(zhuǎn)換
const_cast轉(zhuǎn)換可以將const限定符添加或移除,以便在需要更改底層值時(shí)使用,但要注意的是,const_cast轉(zhuǎn)換可能會(huì)導(dǎo)致未定義行為。
例如:
const int a = 100;
int& b = const_cast<int&>(a);
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-526526.html
到了這里,關(guān)于【036】讀懂C++的強(qiáng)制類型轉(zhuǎn)換static_cast、const_cast、dynamic_cast以及reinterpret_cast的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!