C++的dynamic示例代碼詳解
在C++編程中,dynamic_cast 是處理多態(tài)類(lèi)型轉(zhuǎn)換的關(guān)鍵工具,允許在復(fù)雜繼承結(jié)構(gòu)中安全地將基類(lèi)指針或引用轉(zhuǎn)換為派生類(lèi)指針或引用。通過(guò)利用運(yùn)行時(shí)類(lèi)型信息(RTTI),dynamic_cast 在轉(zhuǎn)換失敗時(shí)返回 nullptr 或拋出異常,從而確保類(lèi)型安全。這使得它在處理多態(tài)對(duì)象和確保代碼健壯性方面不可或缺。
這段代碼的目的是使用 C++ 中的 dynamic_cast 進(jìn)行類(lèi)型轉(zhuǎn)換,來(lái)判斷指針指向的實(shí)際對(duì)象類(lèi)型。以下是對(duì)這段代碼的分析:
代碼示例
class Entity {
public:
virtual ~Entity() = default; // 為了使用 dynamic_cast,基類(lèi)需要有至少一個(gè)虛函數(shù)
};
class Player : public Entity {
// Player 類(lèi)的定義
};
class Enemy : public Entity {
// Enemy 類(lèi)的定義
};
int main() {
Player* player = new Player(); // 創(chuàng)建一個(gè) Player 對(duì)象
Entity* actuallyEnemy = new Enemy(); // 創(chuàng)建一個(gè) Enemy 對(duì)象,并用 Entity* 指針指向它
Entity* actuallyPlayer = player; // 用 Entity* 指針指向 Player 對(duì)象
Player* po = dynamic_cast<Player*>(actuallyEnemy); // 試圖將 actuallyEnemy 轉(zhuǎn)換為 Player*
if (po)
{
// 用來(lái)檢測(cè)是否轉(zhuǎn)換成功
}
Player* p1 = dynamic_cast<Player*>(actuallyPlayer); // 將 actuallyPlayer 轉(zhuǎn)換為 Player*
}dynamic_cast 解析
dynamic_cast<Player*>(actuallyEnemy):actuallyEnemy實(shí)際上指向的是一個(gè)Enemy對(duì)象。dynamic_cast會(huì)檢查actuallyEnemy是否可以合法轉(zhuǎn)換為Player*。- 由于
Enemy不能轉(zhuǎn)換為Player,轉(zhuǎn)換失敗,po會(huì)被設(shè)置為nullptr。
dynamic_cast<Player*>(actuallyPlayer):actuallyPlayer實(shí)際上指向的是一個(gè)Player對(duì)象。- 由于
actuallyPlayer可以合法轉(zhuǎn)換為Player*,所以p1會(huì)指向Player對(duì)象。
總結(jié)
po將為nullptr,因?yàn)?actuallyEnemy指向一個(gè)Enemy對(duì)象,而不能轉(zhuǎn)換為Player*。p1將指向Player對(duì)象,因?yàn)?actuallyPlayer原本就是Player*類(lèi)型。
這種類(lèi)型轉(zhuǎn)換檢查在需要確定指針指向的實(shí)際對(duì)象類(lèi)型時(shí)非常有用,特別是在繼承層次結(jié)構(gòu)復(fù)雜的情況下。
RTTI(Run-Time Type Information,運(yùn)行時(shí)類(lèi)型信息)是C++中提供的一種機(jī)制,允許程序在運(yùn)行時(shí)動(dòng)態(tài)地識(shí)別對(duì)象的類(lèi)型。這在面向?qū)ο缶幊讨杏葹橹匾?,尤其是在多態(tài)性和復(fù)雜繼承層次結(jié)構(gòu)中。
RTTI 的工作原理
RTTI 是通過(guò)在類(lèi)中保存額外的信息實(shí)現(xiàn)的,這些信息包括對(duì)象的實(shí)際類(lèi)型以及類(lèi)型的層次結(jié)構(gòu)。在編譯時(shí),編譯器為啟用了 RTTI 的類(lèi)生成這些信息。在運(yùn)行時(shí),當(dāng)使用 dynamic_cast 或 typeid 操作符時(shí),RTTI 會(huì)進(jìn)行類(lèi)型檢查或返回對(duì)象的類(lèi)型信息。
RTTI 的用途
1.動(dòng)態(tài)類(lèi)型轉(zhuǎn)換 (dynamic_cast):
dynamic_cast 是 C++ 提供的一種用于在繼承層次結(jié)構(gòu)中進(jìn)行安全類(lèi)型轉(zhuǎn)換的操作符。它允許你將基類(lèi)指針或引用轉(zhuǎn)換為派生類(lèi)指針或引用,并在轉(zhuǎn)換失敗時(shí)返回 nullptr(對(duì)于指針)或拋出異常(對(duì)于引用)。
例如,在之前的代碼示例中,我們使用 dynamic_cast<Player*>(actuallyEnemy) 來(lái)檢查 actuallyEnemy 是否可以被轉(zhuǎn)換為 Player*。這是通過(guò) RTTI 實(shí)現(xiàn)的,RTTI 會(huì)在后臺(tái)檢查 actuallyEnemy 實(shí)際指向的對(duì)象類(lèi)型是否為 Player 或其派生類(lèi)。
2.類(lèi)型識(shí)別 (typeid):
typeid操作符返回一個(gè)std::type_info對(duì)象,表示對(duì)象的實(shí)際類(lèi)型。通過(guò)typeid,你可以比較兩個(gè)對(duì)象的類(lèi)型或獲取類(lèi)型的名字。- 例如:
Entity* entity = new Player();
if (typeid(*entity) == typeid(Player)) {
std::cout << "Entity is of type Player" << std::endl;
}這里的 typeid(*entity) 會(huì)返回 Player 類(lèi)型的信息。
RTTI 的實(shí)現(xiàn)細(xì)節(jié)
RTTI 的實(shí)現(xiàn)通常依賴于編譯器對(duì)每個(gè)啟用了 RTTI 的類(lèi)添加一個(gè)稱(chēng)為 vtable(虛函數(shù)表)的結(jié)構(gòu)。在這個(gè)表中包含了虛函數(shù)指針和類(lèi)型信息指針。在執(zhí)行 dynamic_cast 或 typeid 操作時(shí),程序會(huì)檢查這個(gè) vtable,來(lái)確定對(duì)象的實(shí)際類(lèi)型。
- vtable(虛函數(shù)表):當(dāng)一個(gè)類(lèi)有虛函數(shù)或啟用了 RTTI,編譯器會(huì)為這個(gè)類(lèi)生成一個(gè) vtable。vtable 是一個(gè)指針數(shù)組,指向該類(lèi)的虛函數(shù),以及與 RTTI 相關(guān)的類(lèi)型信息。
- vptr(虛函數(shù)指針):每個(gè)對(duì)象實(shí)例中都有一個(gè)隱藏的指針(通常稱(chēng)為 vptr),指向該對(duì)象所屬類(lèi)的 vtable。
在執(zhí)行 dynamic_cast 時(shí),程序會(huì)通過(guò) vptr 訪問(wèn) vtable,從而獲取類(lèi)型信息并進(jìn)行類(lèi)型檢查。
RTTI 的使用場(chǎng)景
多態(tài)性:
- 在多態(tài)性中,基類(lèi)指針或引用可以指向派生類(lèi)對(duì)象。RTTI 使得在運(yùn)行時(shí)能夠安全地轉(zhuǎn)換這些指針或引用,確保訪問(wèn)的是正確的派生類(lèi)方法或?qū)傩浴?/li>
復(fù)雜繼承結(jié)構(gòu):
- 當(dāng)類(lèi)層次結(jié)構(gòu)復(fù)雜,且需要處理未知或不確定的類(lèi)型時(shí),RTTI 提供了一種在運(yùn)行時(shí)檢查和處理不同類(lèi)型的方法。
注意事項(xiàng)
- 性能開(kāi)銷(xiāo):?jiǎn)⒂?RTTI 會(huì)增加程序的內(nèi)存開(kāi)銷(xiāo)和運(yùn)行時(shí)間開(kāi)銷(xiāo),因?yàn)樾枰S護(hù) vtable 和額外的類(lèi)型信息。特別是在嵌入式系統(tǒng)或性能要求苛刻的應(yīng)用中,可能需要考慮這個(gè)因素。
- 編譯器選項(xiàng):在某些情況下,RTTI 可能默認(rèn)被禁用(如某些嵌入式編譯環(huán)境),如果使用
dynamic_cast或typeid,需要確保編譯器啟用了 RTTI 支持。
RTTI 是 C++ 強(qiáng)大和靈活性的一部分,雖然使用 RTTI 可能帶來(lái)一些開(kāi)銷(xiāo),但在需要安全類(lèi)型轉(zhuǎn)換和類(lèi)型檢查的場(chǎng)景下,它是非常有用的工具。
到此這篇關(guān)于C++的dynamic的文章就介紹到這了,更多相關(guān)C++ dynamic內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- C++強(qiáng)制類(lèi)型轉(zhuǎn)換(static_cast、dynamic_cast、const_cast、reinterpret_cast)
- 淺析C++中dynamic_cast和static_cast實(shí)例語(yǔ)法詳解
- C++中的new/delete、構(gòu)造/析構(gòu)函數(shù)、dynamic_cast分析
- 由static_cast和dynamic_cast到C++對(duì)象占用內(nèi)存的全面分析
- C++中的類(lèi)型轉(zhuǎn)換static_cast、dynamic_cast、const_cast和reinterpret_cast總結(jié)
- c++ dynamic_cast與static_cast使用方法示例
- C++ 中dynamic_cast<>的使用方法小結(jié)
相關(guān)文章
visual studio 2019工具里添加開(kāi)發(fā)中命令提示符的方法
這篇文章主要介紹了visual studio 2019工具里添加開(kāi)發(fā)中命令提示符的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03
C語(yǔ)言動(dòng)態(tài)內(nèi)存分配和內(nèi)存操作函數(shù)使用詳解
但是在實(shí)際的編程中,往往會(huì)發(fā)生這種情況,即所需的內(nèi)存空間取決于實(shí)際輸入的數(shù)據(jù),而無(wú)法預(yù)先確定 。為了解決上述問(wèn)題,C語(yǔ)言提供了一些內(nèi)存管理函數(shù),這些內(nèi)存管理函數(shù)可以按需要?jiǎng)討B(tài)的分配內(nèi)存空間,也可把不再使用的空間回收再次利用2022-12-12
C++實(shí)現(xiàn)圖形界面時(shí)鐘表盤(pán)代碼
這篇文章主要介紹了C++實(shí)現(xiàn)圖形界面時(shí)鐘表盤(pán)代碼,涉及坐標(biāo)函數(shù)的應(yīng)用及圖形界面程序設(shè)計(jì),需要的朋友可以參考下2014-10-10
利用C語(yǔ)言實(shí)現(xiàn)任務(wù)調(diào)度的示例代碼
這篇文章主要為大家詳細(xì)介紹了如何利用純C語(yǔ)言實(shí)現(xiàn)任務(wù)調(diào)度(可用于STM32、C51等單片機(jī)),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2023-04-04
C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易的三子棋游戲
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易的三子棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-12-12
C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易文本編譯器
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易文本編譯器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-05-05

