溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何理解C++的轉(zhuǎn)換手段并與Explicit關(guān)鍵詞配合使用

發(fā)布時間:2021-10-23 15:30:26 來源:億速云 閱讀:131 作者:iii 欄目:編程語言

這篇文章主要介紹“如何理解C++的轉(zhuǎn)換手段并與Explicit關(guān)鍵詞配合使用”,在日常操作中,相信很多人在如何理解C++的轉(zhuǎn)換手段并與Explicit關(guān)鍵詞配合使用問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”如何理解C++的轉(zhuǎn)換手段并與Explicit關(guān)鍵詞配合使用”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

C中我們會進行各種類型的強制轉(zhuǎn)化,而在C中我們經(jīng)常可以看到這種轉(zhuǎn)換

memset(OTA_FLAG_ADDRESS,(uint8_t*)&OTA_Flag,sizeof(OTA_Flag));

而C++的類型轉(zhuǎn)化和C差別很多,那么C++里面的類型轉(zhuǎn)化是怎么用的呢。C++除了隱式轉(zhuǎn)換和顯示轉(zhuǎn)化,顯示轉(zhuǎn)化是我們熟知,有四個顯示轉(zhuǎn)化函數(shù):static_cast、dynamic_cast、const_cast、reinterpret_cast,主要運用于繼承關(guān)系類間的強制轉(zhuǎn)化。

隱式轉(zhuǎn)化

c++語言不會直接將兩個不同類型的值相加,二十先根據(jù)類型轉(zhuǎn)化規(guī)則設(shè)法將運算對象的類型統(tǒng)一后再求值。例如 int value = 3.14  +3;這個程序是可以編譯通過的,只不過編譯器可能會警告改運算損失了精度。這樣的類型轉(zhuǎn)化是自動運行,無需程序員介入,因此,它們被稱為隱式轉(zhuǎn)換

何時會發(fā)生隱式轉(zhuǎn)化:

在下面的情況中,編譯器會自動的轉(zhuǎn)化運算對象的類型:

  1. 鴻蒙官方戰(zhàn)略合作共建——HarmonyOS技術(shù)社區(qū)

  2. 在大多數(shù)表達式中,需要將比int類型小的整型值首先提升到較大的整數(shù)類型會進行隱式轉(zhuǎn)化

  3. 在條件中,非布爾值轉(zhuǎn)換成布爾類型

  4. 初始化過程中,初始值轉(zhuǎn)化成變量的類型;在賦值語句中,右側(cè)運算對象轉(zhuǎn)化成左側(cè)運算對象的類型

  5. 函數(shù)調(diào)用時候也會發(fā)生類型轉(zhuǎn)化(實參類型轉(zhuǎn)化)

顯示轉(zhuǎn)化

C風格的強制轉(zhuǎn)換(Type Cast)容易理解,不管什么類型的轉(zhuǎn)換都可以使用使用下面的方式

Type b = (Type)a;

當然,C++也是支持C風格的強制轉(zhuǎn)換,但是C風格的強制轉(zhuǎn)換可能帶來一些隱患,讓一些問題難以察覺.所以C++提供了一組可以用在不同場合的強制轉(zhuǎn)換的函數(shù).

C++提供了四種強制類型轉(zhuǎn)化的函數(shù),分別是:

static_cast,命名上理解是靜態(tài)類型轉(zhuǎn)換。大部分C實現(xiàn)的轉(zhuǎn)化,用這個函數(shù)就可以了。

const_cast,字面上理解就是去const屬性。

dynamic_cast,命名上理解是動態(tài)類型轉(zhuǎn)換。如子類和父類之間的多態(tài)類型轉(zhuǎn)換。

reinterpret_cast,僅僅重新解釋類型,但沒有進行二進制的轉(zhuǎn)換。

static_cast:

任何具有明確定義的類型轉(zhuǎn)化,只要不包含底層const,都可以使用static_cast,舉一個例子。

double slop = static_cast<double>(j) / i;//進行強制轉(zhuǎn)化成double int*pn =&n; double*dp = static_cast<double*>(&pn) //無關(guān)類型指針轉(zhuǎn)換,編譯錯誤  void*p = &n;  double*d = static_cast<double*>(&p) //將void*轉(zhuǎn)化為初始的指針類型

static_cast強制轉(zhuǎn)換只會在編譯時檢查,但沒有運行時類型檢查來保證轉(zhuǎn)換的安全性。同時,static_cast也不能去掉expression的const、volitale、或者__unaligned屬性。

const_cast:

const_cast<>可以實現(xiàn)將const  指針類型轉(zhuǎn)普通指針,const_cast操作不能在不同的種類間轉(zhuǎn)換。相反,它僅僅把一個它作用的表達式轉(zhuǎn)換成常量。它可以使一個本來不是const類型的數(shù)據(jù)轉(zhuǎn)換成const類型的,或者把const屬性去掉。如果一個對象本身不是一個常量,使用強制類型轉(zhuǎn)化獲得寫權(quán)限是合法的行為。然而如果對象是一個常量,再使用const_cast執(zhí)行寫操作就會產(chǎn)生未定義的后果。

只有const_cast能改變表達式的常量屬性,使用其他形式的命名強制類型轉(zhuǎn)化改變表達式的常量屬性都將引發(fā)編譯器錯誤。同樣的,也不能用const_cast改變表達式的類型:

const char *cp;  char *q = static_cast<char *>(cp);//錯誤:static_cast不能轉(zhuǎn)換掉const性質(zhì) static_cast<string>(cp);//正確:字符串字面值轉(zhuǎn)換成string類型 const_cast<string>(cp);//錯誤:const_cast 只改變常量屬性 const_cast<char*>(cp);//正確 const int p = 0; int &rb = const_cast<int&>(p);//正確 rb =10;

dynamic_cast:

1.其他三種都是編譯時完成的,dynamic_cast是運行時處理的,運行時要進行類型檢查。

2.不能用于內(nèi)置的基本數(shù)據(jù)類型的強制轉(zhuǎn)換。

3.dynamic_cast轉(zhuǎn)換如果成功的話返回的是指向類的指針或引用,轉(zhuǎn)換失敗的話則會返回NULL。

4.使用dynamic_cast進行轉(zhuǎn)換的,基類中一定要有虛函數(shù),否則編譯不通過。可以從父類轉(zhuǎn)基類,但是可能為空

5.在類的轉(zhuǎn)換時,在類層次間進行上行轉(zhuǎn)換時,dynamic_cast和static_cast的效果是一樣的。在進行下行轉(zhuǎn)換時,dynamic_cast具有類型檢查的功能,比static_cast更安全。向上轉(zhuǎn)換即為指向子類對象的向下轉(zhuǎn)換,即將父類指針轉(zhuǎn)化子類指針。向下轉(zhuǎn)換的成功與否還與將要轉(zhuǎn)換的類型有關(guān),即要轉(zhuǎn)換的指針指向的對象的實際類型與轉(zhuǎn)換以后的對象類型一定要相同,否則轉(zhuǎn)換失敗。

class BaseClass {  public:     int Num;     virtualvoid foo(){}; //基類必須有虛函數(shù)。保持多臺特性才能使用dynamic_cast   };  DerivedClass: public BaseClass {  public:    char*m_szName[100];   void bar(){}; }; int main(int argc,char** argv) {   BaseClass* pb =new DerivedClass();   DerivedClass *pd1 = static_cast<DerivedClass *>(pb); //子類->父類,靜態(tài)類型轉(zhuǎn)換,正確但不推薦   DerivedClass *pd2 = dynamic_cast<DerivedClass *>(pb); //子類->父類,動態(tài)類型轉(zhuǎn)換,正確   BaseClass* pb2 =new BaseClass();   DerivedClass *pd21 = static_cast<DerivedClass *>(pb2); //父類->子類,靜態(tài)類型轉(zhuǎn)換,危險!訪問子類m_szName成員越界   DerivedClass *pd22 = dynamic_cast<DerivedClass *>(pb2); //父類->子類,動態(tài)類型轉(zhuǎn)換,安全的。結(jié)果是NULL

reinterpret_cast:

實現(xiàn)指針轉(zhuǎn)整形,整形轉(zhuǎn)指針.reinterpret_cast是強制類型轉(zhuǎn)換符用來處理無關(guān)類型轉(zhuǎn)換的,通常為操作數(shù)的位模式提供較低層次的重新解釋!但是它僅僅是重新解釋了給出的對象的比特模型,并沒有進行二進制的轉(zhuǎn)換!

它是用在任意的指針之間的轉(zhuǎn)換,引用之間的轉(zhuǎn)換,指針和足夠大的int型之間的轉(zhuǎn)換,整數(shù)到指針的轉(zhuǎn)換。最普通的用途就是在函數(shù)指針類型之間進行轉(zhuǎn)換。

請看一個簡單代碼

int doSomething(){return 0;}; typedef void(*FuncPtr)(); //FuncPtr is 一個指向函數(shù)的指針,該函數(shù)沒有參數(shù),返回值類型為 void FuncPtr funcPtrArray[10]; //10個FuncPtrs指針的數(shù)組 讓我們假設(shè)你希望(因為某些莫名其妙的原因)把一個指向下面函數(shù)的指針存入funcPtrArray數(shù)組: funcPtrArray[0] =&doSomething;// 編譯錯誤!類型不匹配,reinterpret_cast可以讓編譯器以你的方法去看待它們:funcPtrArray funcPtrArray[0] = reinterpret_cast<FuncPtr>(&doSomething); //不同函數(shù)指針類型之間進行轉(zhuǎn)換

explicit關(guān)鍵字(顯示的類型轉(zhuǎn)化運算符)

C++提供了關(guān)鍵字explicit,可以阻止不應(yīng)該允許的經(jīng)過轉(zhuǎn)換構(gòu)造函數(shù)進行的隱式轉(zhuǎn)換的發(fā)生。即聲明為explicit的構(gòu)造函數(shù)不能在隱式轉(zhuǎn)換中使用。

explicit關(guān)鍵字只能用于類內(nèi)部的構(gòu)造函數(shù)聲明上,而不能用在類外部的函數(shù)定義上?,F(xiàn)在Things類像這樣:

class Things { public:    Things(const std::string&name ="");      explicit operator int() const{return val;}      //編譯器不會自動執(zhí)行這一類型的 };

下面再看個好一點的例子進行對比一下:

// 類的通過構(gòu)造函數(shù)的隱式轉(zhuǎn)換: #include <iostream> using namespace std;  class A {};  class B { public:   // conversion from A (constructor):   B (const A& x) {}   // conversion from A (assignment):   B& operator= (const A& x) {return *this;}   // conversion to A (type-cast operator)   operator A() {return A();} };  int main () {   A foo;   B bar = foo;    // 調(diào)用構(gòu)造函數(shù)實現(xiàn)隱式類型轉(zhuǎn)換   bar = foo;      // calls assignment   foo = bar;      // calls type-cast operator,相當于 foo = A(bar);   return 0; }

再看使用explicit的一個例子:

#include <iostream> using namespace std;  class A {};  class B { public:   explicit B (const A& x) {}   B& operator= (const A& x) {return *this;}   operator A() {return A();} };  void fn (B x) {}  // 當我們希望x只能是B類型時,我們就需要禁止隱式類型轉(zhuǎn)換  int main () {   A foo;   B bar (foo);  // 必須顯式類型轉(zhuǎn)換,不再允許B bar = foo;    bar = foo;   foo = bar;  //  fn (foo);  // 不允許隱式類型轉(zhuǎn)換   fn (bar);      return 0; }

到此,關(guān)于“如何理解C++的轉(zhuǎn)換手段并與Explicit關(guān)鍵詞配合使用”的學習就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI