c語言強制轉化的正確使用:c強制類型轉換規則

dynamic_cast是四個強制類型轉換操作符中最特殊的一個,它支持運行時識別指針或引用。

>>>>>>>>>>>編譯器的RTTI設置>>>>>>>>>>>

dynamic_cast提供RTTI(Run-Time Type Information),也就是運行時類型識別。它對編譯器有要求,需要編譯器啟動「運行時類型信息」這一選項。當編譯器不開啟RTTI時,運行含有dynamic_cast操作符的程序時會出現一個警告:

warning C4541: 「dynamic_cast」用在了帶 /GR- 的多態類型「ANIMAL」上;可能導致不可預知的行為

VS2010在默認下是開啟RTTI的,也可以自己手動去開啟或者關閉,操作如下:

視圖->解決方案資源管理器
C++強制類型轉換操作符 dynamic_cast
在打開的解決方案管理器中,對着項目名稱右擊,選擇屬性
C++強制類型轉換操作符 dynamic_cast
配置屬性-〉C/C++
C++強制類型轉換操作符 dynamic_cast

>>>>>>>>>>>>>步入正題>>>>>>>>>>>>>

  • dynamic_cast主要用於「安全地向下轉型」

dynamic_cast用於類繼承層次間的指針或引用轉換。主要還是用於執行「安全的向下轉型(safe downcasting)」,也即是基類對象的指針或引用轉換為同一繼承層次的其他指針或引用。至於「先上轉型」(即派生類指針或引用類型轉換為其基類類型),本身就是安全的,儘管可以使用dynamic_cast進行轉換,但這是沒必要的, 普通的轉換已經可以達到目的,畢竟使用dynamic_cast是需要開銷的。

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()
{    
    Base *base ;
    Derived *der = new Derived;
    //base = dynamic_cast<Base*>(der); //正確,但不必要。
    base = der; //先上轉換總是安全的
    base->Show(); 
    system("pause");
}

                                   學習交流群:894479708
                        歡迎所有初學和進階者一起討論學習!

dynamic_cast與繼承層次的指針

對於「向下轉型」有兩種情況。一種是基類指針所指對象是派生類類型的,這種轉換是安全的;另一種是基類指針所指對象為基類類型,在這種情況下dynamic_cast在運行時做檢查,轉換失敗,返回結果為0;

#include "stdafx.h"
#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()
{    
    //這是第一種情況
    Base* base = new Derived;
    if(Derived *der= dynamic_cast<Derived*>(base))
    {
        cout<<"第一種情況轉換成功"<<endl;
        der->Show();
        cout<<endl;
    }
    //這是第二種情況
    Base * base1 = new Base;
    if(Derived *der1 = dynamic_cast<Derived*>(base1))
    {
        cout<<"第二種情況轉換成功"<<endl;
        der1->Show();
    }
    else 
    {
        cout<<"第二種情況轉換失敗"<<endl;
    }

                                                           學習交流群:894479708
                                                歡迎所有初學和進階者一起討論學習!
  
    delete(base);
    delete(base1);
    system("pause");
}

運行結果:

      

C++強制類型轉換操作符 dynamic_cast
  • dynamic_cast和引用類型

在前面的例子中,使用了dynamic_cast將基類指針轉換為派生類指針,也可以使用dynamic_cast將基類引用轉換為派生類引用。

同樣的,引用的向上轉換總是安全的:

    Derived c;
    Derived & der2= c;
    Base & base2= dynamic_cast<Base&>(der2);//向上轉換,安全
    base2.Show();

所以,在引用上,dynamic_cast依舊是常用於「安全的向下轉型」。與指針一樣,引用的向下轉型也可以分為兩種情況,與指針不同的是,並不存在空引用,所以引用的dynamic_cast檢測失敗時會拋出一個bad_cast異常:

int main()
{    
    //第一種情況,轉換成功
    Derived b ;
    Base &base1= b;
    Derived &der1 = dynamic_cast<Derived&>(base1);
    cout<<"第一種情況:";
    der1.Show();
    cout<<endl;

    //第二種情況
    Base a ;
    Base &base = a ;
    cout<<"第二種情況:";
    try{
        Derived & der = dynamic_cast<Derived&>(base);
    }
    catch(bad_cast)
      
      
      
                                                           學習交流群:894479708
                                                歡迎所有初學和進階者一起討論學習!
  
      
      
      
      
      
    {
        cout<<"轉化失敗,拋出bad_cast異常"<<endl;
    }
    system("pause");
}

運行結果:

C++強制類型轉換操作符 dynamic_cast
  • 使用dynamic_cast轉換的Base類至少帶有一個虛函數

當一個類中擁有至少一個虛函數的時候,編譯器會為該類構建出一個虛函數表(virtual method table),虛函數表記錄了虛函數的地址。如果該類派生了其他子類,且子類定義並實現了基類的虛函數,那麼虛函數表會將該函數指向新的地址。虛表是C++多態實現的一個重要手段,也是dynamic_cast操作符轉換能夠進行的前提條件。當類沒有虛函數表的時候(也即一個虛函數都沒有定義),dynamic_cast無法使用RTTI,不能通過編譯(個人猜想…有待驗證)。

  當然,虛函數表的建立對效率是有一定影響的,構建虛函數表、由表查詢函數 都需要時間和空間上的消耗。所以,除了必須聲明virtual(對於一個多態基類而言),不要輕易使用virtual函數。對於虛函數的進一步了解,可以查看《Effective C++》

原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/216921.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
投稿專員的頭像投稿專員
上一篇 2024-12-09 00:25
下一篇 2024-12-09 00:25

相關推薦

發表回復

登錄後才能評論