最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++超詳細(xì)講解強(qiáng)制類型轉(zhuǎn)換的用法

 更新時間:2022年06月20日 08:37:22   作者:loongknown  
在C++語言中新增了四個關(guān)鍵字static_cast、const_cast、reinterpret_cast和dynamic_cast。這四個關(guān)鍵字都是用于類型轉(zhuǎn)換的,類型轉(zhuǎn)換(type?cast),是高級語言的一個基本語法。它被實現(xiàn)為一個特殊的運算符,以小括號內(nèi)加上類型名來表示,接下來讓我們一起來詳細(xì)了解

static_cast

static_cast<type-id>(expression)

expression 轉(zhuǎn)換為 type-id 類型。static_cast 是靜態(tài)類型轉(zhuǎn)換,發(fā)生在編譯期。這種轉(zhuǎn)換不會進(jìn)行運行時的動態(tài)檢查(RTTI),因而這種轉(zhuǎn)換可能是不安全的。static_cast 典型應(yīng)用場景如下:

1. 類的層級結(jié)構(gòu)中,基類和子類之間指針或者引用的轉(zhuǎn)換。

上行轉(zhuǎn)換(Upcasting),也即子類像基類方向轉(zhuǎn)換,是安全的。

下行轉(zhuǎn)換(Downcasting),也即基類向子類方向轉(zhuǎn)換,是不安全的,需要程序員自行保證安全轉(zhuǎn)換。

下面舉例說明:

class A {
public:
  virtual void func() {
    std::cout << "A::func()" << std::endl;
  } 
};
class B : public A {
public:
  virtual void func() {
    std::cout << "B::func()" << std::endl;
  }
  void print() {
    std::cout << "B::print()" << std::endl;
  }
};

對于上行轉(zhuǎn)換,肯定是安全的。

  B* pb = new B();
  A* pa = static_cast<A*>(pa);
  pa->func();

對于下行轉(zhuǎn)換:

  A* pa = new B();
  B* pb = static_cast<B*>(pa);
  pb->print();

這里,A* pa = new B();,由于 C++ 的多態(tài)的支持,可以使用基類指針指向子類。這里的轉(zhuǎn)換是安全的,因為 pa 初始化就指向的就是 B。而下面的轉(zhuǎn)換則是不安全的:

  A* pa = new A();
  B* pb = static_cast<B*>(pa);
  pb->print();

此外,對于兩個不存在繼承關(guān)系的兩個類之間轉(zhuǎn)換,總是失敗的,編譯器報錯:

#include <iostream>
class A {
    virtual void func(){}
};
class B {
    virtual void func(){}
};
int main(){
    A* pa = new A();
    B* pb = static_cast<B*>(pa); 
    return 0;
}

2. 基本數(shù)據(jù)類型間的轉(zhuǎn)換。這種轉(zhuǎn)換也是不安全的,需要程序員自行保證安全轉(zhuǎn)換。 例如 int 轉(zhuǎn) short,直接高位截斷;而 short 轉(zhuǎn) int 則高位根據(jù)符號位填充。兩種不同類型指針間相互轉(zhuǎn)換是相當(dāng)危險的,例如 int* 轉(zhuǎn) float*。將 int 轉(zhuǎn)換為指針類型也是危險的轉(zhuǎn)換,例如 float* p = static_cast<float*>(0X2edf);

3. 將 void 類型轉(zhuǎn)換為其他類型的指針。 顯然這種轉(zhuǎn)換也是不安全的,需要程序員自行保證安全轉(zhuǎn)換。

4. 把其他類型轉(zhuǎn)換為 void 類型。

有轉(zhuǎn)換構(gòu)造函數(shù)或者類型轉(zhuǎn)換函數(shù)的類與其它類型之間的轉(zhuǎn)換。例如:

#include <iostream>
class Point{
public:
    Point(double x, double y): m_x(x), m_y(y){ }
    Point(double& x): m_x(x), m_y(1.1){ }
public:
    operator double() const { return m_x; }  //類型轉(zhuǎn)換函數(shù)
    void print() {
        std::cout << "m_x: " << m_x << "  m_y: " << m_y << std::endl;
    }
private:
    double m_x;
    double m_y;
};
int main() {
    Point p1(12.5, 23.8);
    double x= static_cast<double>(p1);
    // std::cout << x << std::endl;
    Point p2 = static_cast<Point>(x);
    // p2.print();
    return 0;
}

dynamic_cast

dynamic_cast<type-id>(expression)

expression 轉(zhuǎn)換為 type-id 類型,type-id 必須是類的指針、類的引用或者是 void *;如果 type-id 是指針類型,那么 expression 也必須是一個指針;如果 type-id 是一個引用,那么 expression 也必須是一個引用。

dynamic_cast 提供了運行時的檢查。對于指針類型,在運行時會檢查 expression 是否真正的指向一個 type-id 類型的對象,如果是,則能進(jìn)行正確的轉(zhuǎn)換;否則返回 nullptr。對于引用類型,若是無效轉(zhuǎn)換,則在運行時會拋出異常 std::bad_cast。

T1 obj;
T2* pObj = dynamic_cast<T2*>(&obj);    // 無效轉(zhuǎn)換返回 nullptr
T2& refObj = dynamic_cast<T2&>(obj);   // 無效轉(zhuǎn)換拋出 bad_cast 異常

上行轉(zhuǎn)換:其實和 static_cast 是一樣的,一般肯定能成功。例如前面用到的例子:

// A->B
B* pb = new B();
A* pa = static_cast<A*>(pa);  

但是,下面這種繼承關(guān)系會轉(zhuǎn)換失?。?/p>

#include <iostream>
/*    A
     / \
    V  V
    B  C
     \/
     v
     D   */
class A {
    virtual void func(){}
};
class B : public A {
    void func(){}
};
class C : public A {
    void func(){}
};
class D : public B, public C {
    void func(){}
};
int main(){
    D* pd = new D();
    A* pa = dynamic_cast<A*>(pd);
    return 0;
}

上面這個例子,雖然也是上行轉(zhuǎn)換,但是存在兩條路徑,在 B 和 C 都繼承于 A,并且有虛函數(shù)實現(xiàn),上行轉(zhuǎn)換不知道從哪條路徑進(jìn)行轉(zhuǎn)換。下面的寫法則沒問題:

  D* pd = new D();
  B* pb = dynamic_cast<B*>(pd);
  A* pa = dynamic_cast<A*>(pb);

下行轉(zhuǎn)換:看個例子。

#include <iostream>
class A {
    virtual void func(){}
};
class B : public A {
    void func(){}
};
int main(){
    A* pa1 = new B();
    A* pa2 = new A();
    B *pb1 = dynamic_cast<B*>(pa1); // ok
    B *pb2 = dynamic_cast<B*>(pa2); // pb2 is a nullptr!
    return 0;
}

其實 dynamic_cast 本質(zhì)只支持上行轉(zhuǎn)換,只會沿著繼承鏈向上遍歷,找到目標(biāo)類型則轉(zhuǎn)換成功,否則失敗。dynamic_cast 看似支持下行轉(zhuǎn)換,這都是多態(tài)的緣故。上面的例子,pa1 雖然類型是 A,但實際指向 B,沿著 B 向上可以找到 B,因為第一個轉(zhuǎn)換可以成功。而 pa2 指向 A,沿著 A 向上找不到 B 類型,因而轉(zhuǎn)換失敗。

因而在有繼承關(guān)系的類的轉(zhuǎn)換時候, static_cast 轉(zhuǎn)換總是成功的, dynamic_cast 顯然比 static_cast 更加安全。

const_cast

const_cast 用來去掉表達(dá)式的 const 修飾或 volatile 修飾,也就是將 constvolatile 類型轉(zhuǎn)換為非 const 或 非 volatile 類型。

#include <iostream>
int main(){
    const int n = 111;
    int *p = const_cast<int*>(&n);
    *p = 222;
    std::cout<< "n = " << n << std::endl;
    std::cout<< "*p = " << *p << std::endl;
    return 0;
}

這里需要注意:按照正常理解,n 的打印值應(yīng)該是 222。但是,由于編譯器的常量傳播優(yōu)化,std::cout<< "n = " << n << std::endl; 會被編譯器替換成類似 std::cout<< "n = " << 111 << std::endl; 的語義。

reinterpret_cast

reinterpret_cast 轉(zhuǎn)換直接對二進(jìn)制位按照目標(biāo)類型重新解釋,非常粗暴,所以風(fēng)險很高,慎重使用。

#include <iostream>
int main(){
    char str[]="hello world!";
    float *p = reinterpret_cast<float*>(str);
    std::cout << *p << std::endl;  // 1.14314e+27
    return 0;
}

到此這篇關(guān)于C++超詳細(xì)講解強(qiáng)制類型轉(zhuǎn)換的用法的文章就介紹到這了,更多相關(guān)C++強(qiáng)制類型轉(zhuǎn)換內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 對C語言中遞歸算法的深入解析

    對C語言中遞歸算法的深入解析

    C通過運行時堆棧支持遞歸函數(shù)的實現(xiàn)。遞歸函數(shù)就是直接或間接調(diào)用自身的函數(shù)
    2013-07-07
  • C++如何實現(xiàn)簡單的計時器詳解

    C++如何實現(xiàn)簡單的計時器詳解

    因為最近閑著無聊就想著要不用C++寫點什么東西,仔細(xì)想了想其實自己的C++學(xué)的也不怎么好,寫個簡單的計時器吧!所以下面這篇文章主要介紹了利用C++如何實現(xiàn)簡單的計時器,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-01-01
  • C語言實戰(zhàn)之浪漫煙花表白程序代碼

    C語言實戰(zhàn)之浪漫煙花表白程序代碼

    這篇文章主要介紹了C語言實戰(zhàn)之浪漫煙花表白程序代碼,需要的朋友可以參考下
    2021-04-04
  • C/C++在VScode中的配置教程詳解

    C/C++在VScode中的配置教程詳解

    這篇文章主要介紹了C/C++在VScode中的配置教程詳解,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04
  • QT利用QPainter繪制三維餅狀圖

    QT利用QPainter繪制三維餅狀圖

    這篇文章主要為大家詳細(xì)介紹了如何利用QPainter實現(xiàn)三維餅狀圖的繪制,由于Qt中沒有三維餅狀圖的繪制組件,因此只能自行繪制,感興趣的可以動手嘗試一下
    2022-06-06
  • 詳解C++14中返回類型推導(dǎo)的使用

    詳解C++14中返回類型推導(dǎo)的使用

    這篇文章主要為大家詳細(xì)介紹了C++14中返回類型推導(dǎo)的使用,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-07-07
  • C++?list容器merge算法的使用以及注意事項

    C++?list容器merge算法的使用以及注意事項

    這篇文章主要介紹了C++?list容器merge算法的使用以及注意事項,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • C++實現(xiàn)十六進(jìn)制字符串轉(zhuǎn)換成int整形值的示例

    C++實現(xiàn)十六進(jìn)制字符串轉(zhuǎn)換成int整形值的示例

    今天小編就為大家分享一篇關(guān)于C++實現(xiàn)十六進(jìn)制字符串轉(zhuǎn)換成int整形值的示例,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • 使用opencv拉伸圖像擴(kuò)大分辨率示例

    使用opencv拉伸圖像擴(kuò)大分辨率示例

    這篇文章主要介紹了使用opencv拉伸圖像擴(kuò)大分辨率示例,需要的朋友可以參考下
    2014-04-04
  • 利用C++開發(fā)一個protobuf動態(tài)解析工具

    利用C++開發(fā)一個protobuf動態(tài)解析工具

    數(shù)據(jù)庫中存儲的protobuf序列化的內(nèi)容,有時候查問題想直接解析查看內(nèi)容。很多編碼在網(wǎng)上很容易找到編解碼工具,但protobuf沒有找到編解碼工具,可能這樣的需求比較少吧,那就自己用C++實現(xiàn)一個,感興趣的可以了解一下
    2023-01-01

最新評論

洪洞县| 永定县| 民权县| 垣曲县| 林口县| 济阳县| 利川市| 高要市| 揭东县| 湖北省| 宁陵县| 荆州市| 淮北市| 丽水市| 信阳市| 青浦区| 柳林县| 旬阳县| 华宁县| 泰安市| 嘉善县| 东乌珠穆沁旗| 牟定县| 宜宾县| 宁化县| 丹东市| 比如县| 高唐县| 岫岩| 咸阳市| 蓝山县| 乌拉特中旗| 新巴尔虎右旗| 青龙| 凯里市| 营口市| 佛冈县| 大兴区| 松阳县| 新邵县| 达孜县|