C++11新特性之四種類型轉(zhuǎn)換cast說明
引言
C++11引入了四種類型轉(zhuǎn)換接口,它們分別是static_cast、const_cast、dynamic_cast、reinterpret_cast。
為什么要使用這四種轉(zhuǎn)換呢?
給出面向?qū)ο缶幊毯兔嫦驅(qū)ο笤O(shè)計的五個基本原則,SOLID原則。
- Single Responsibility Principle:單一職責(zé)原則
- Open Closed Principle:開閉原則
- Liskov Substitution Principle:里氏替換原則
- Law of Demeter:迪米特法則
- Interface Segregation Principle:接口隔離原則
- Dependence Inversion Principle:依賴倒置原則
這里不詳細(xì)敘述五個基本原則,我們使用的cast接口和里氏替換原則有關(guān)。
里氏替換原則: “派生類(子類)對象可以在程式中代替其基類(超類)對象。” 以上內(nèi)容并非利斯科夫的原文,而是譯自羅伯特·馬?。≧obert Martin)對原文的解讀[1]。
1、static_cast
1.1 基本類型轉(zhuǎn)換
1.2 類的上行轉(zhuǎn)換(安全)
用于子類指針或引用轉(zhuǎn)換為父類指針或引用。
#include <iostream> using namespace std; class Base { public: Base() {}; virtual void Show() { cout << "This is Base class"; } }; class Derived :public Base { public: Derived() {}; void Show() { cout << "This is Derived class"; } }; int main() { Derived* der = new Derived; auto Derived = static_cast<Base*> (der); //向上轉(zhuǎn)換一直是安全的 Derived->Show(); system("pause"); }
輸出結(jié)果為
This is Derived class
存在虛函數(shù)重載,則父類的函數(shù)被隱藏不能使用。
由于使用dynamic_cast
和static_cast
方法會存在開銷,則一般使用下列方法進(jìn)行向上轉(zhuǎn)換。
class Base { public: Base(){}; virtual void Show(){cout<<"This is Base class";} }; class Derived:public Base { public: Derived(){}; void Show(){cout<<"This is Derived class";} }; int main() { Base *base ; Derived *der = new Derived; //向上轉(zhuǎn)換總是安全 base = der; base->Show(); system("pause"); }
1.3 類的下行轉(zhuǎn)換(不安全)
將父類指針、引用轉(zhuǎn)換為子類指針、引用,但需要程序員自己檢查,因此這種轉(zhuǎn)換方式也不存在額外的開銷。
2、const_cast
2.1 改變常量屬性
- 常量指針轉(zhuǎn)化為非常量指針;
- 常量引用轉(zhuǎn)化為非常量引用;
- 常量對象轉(zhuǎn)化為非常量對象
3、dynamic_cast
該轉(zhuǎn)換是運(yùn)行時轉(zhuǎn)換,其余都是編譯時轉(zhuǎn)換。主要用于安全的向下進(jìn)行轉(zhuǎn)換。同時當(dāng)指針是智能指針時,使用dynamic_cast向下轉(zhuǎn)換不能成功,需使用dynamic_point_cast
來進(jìn)行轉(zhuǎn)換。
3.1 類的上行轉(zhuǎn)換(安全)
此處和static_cast是一樣的,不再過多敘述。
#include <iostream> using namespace std; class Base { public: Base() {}; virtual void Show() { cout << "This is Base calss"; } }; class Derived :public Base { public: Derived() {}; void Show() { cout << "This is Derived class"; } }; int main() { Derived* der = new Derived; auto Derived = dynamic_cast<Base*> (der); //向上轉(zhuǎn)換一直是安全的 Derived->Show(); system("pause"); }
3.2 類的下行轉(zhuǎn)換(安全)
因?yàn)橛蓄愋蜋z查所以是安全的,但類型檢查需要運(yùn)行時類型信息,這個信息位于虛函數(shù)表中,所以必須要有虛函數(shù)
,否則會轉(zhuǎn)換失敗。
在dynamic_cast轉(zhuǎn)換中分為兩種情況。
1、當(dāng)基類指針指向派生對象時能夠安全轉(zhuǎn)換。
2、基類指針指向基類時會做檢查,轉(zhuǎn)換失敗,返回結(jié)果0。
#include <iostream> using namespace std; class Base { public: Base() {}; virtual void Show() { cout << "This is Base class" << endl; } }; class Derived :public Base { public: Derived() {}; void Show() { cout << "This is Derived class" << endl; } }; int main() { //第一種情況 Base* base = new Derived; Derived* der = dynamic_cast<Derived*>(base); //基類指針指向派生類對象時能夠安全轉(zhuǎn)換 der->Show(); //第二種情況 Base *base1 = new Base; if (Derived* der1 = dynamic_cast<Derived*> (base1)) { der1->Show(); } else { cout << "error!"; } delete(base); delete(base1); system("pause"); }
This is Derived class
error!
引用則和指針不同,指針在C++11中存在空指針,而引用不存在空引用,會引發(fā)bad_cast
異常。
#include <iostream> using namespace std; class Base { public: Base() {}; virtual void Show() { cout << "This is Base class" << endl; } }; class Derived :public Base { public: Derived() {}; void Show() { cout << "This is Derived class" << endl; } }; int main() { //基類引用子類 Derived b; Base& base1 = b; Derived& der1 = dynamic_cast<Derived&>(base1); der1.Show(); //基類引用基類 Base a; Base& base2 = a; try { Derived& der2 = dynamic_cast<Derived&>(base2); } catch(bad_cast) { cout << "bad_cast error!!" << endl; } system("pause"); }
This is Derived class
bad_cast error!!
4、reinterpret_cast
4.1 非關(guān)聯(lián)類型的轉(zhuǎn)換
操作結(jié)果是一個指針到其他指針的二進(jìn)制拷貝,沒有類型檢查。
總結(jié)
到此這篇關(guān)于C++11新特性之四種類型轉(zhuǎn)換cast說明的文章就介紹到這了,更多相關(guān)C++11類型轉(zhuǎn)換cast內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++數(shù)據(jù)結(jié)構(gòu)之鏈表詳解
這篇文章主要介紹了C++數(shù)據(jù)結(jié)構(gòu)之鏈表的創(chuàng)建的相關(guān)資料,希望通過本文幫助到大家,讓大家理解掌握這部分內(nèi)容,需要的朋友可以參考下2021-08-08Qt數(shù)據(jù)庫應(yīng)用之超級自定義委托
Qt中需要用到自定義委托的情形很多,比如提供下拉框選擇,進(jìn)度條展示下載進(jìn)度啥的,默認(rèn)的單元格是沒有這些效果的,需要自己單獨(dú)用委托的形式來展示。本文將為大家介紹Qt中如何進(jìn)行超級自定義委托,需要的可以參考一下2022-03-03VC外部符號錯誤_main,_WinMain@16,__beginthreadex解決方法
這篇文章主要介紹了VC外部符號錯誤_main,_WinMain@16,__beginthreadex解決方法,實(shí)例分析了比較典型的錯誤及對應(yīng)的解決方法,需要的朋友可以參考下2015-05-05