C++中的Cast

C++中的Cast

引言


在一次看More Effective C++中,有一節提到了《Prefer C++-Style Casts》。其中列舉許多C++ Cast的一些好處,當然這些都是相對於C語言中的強制轉換這類而言的。

所以首先來了解C++中的Cast。



一、Dynamic_Cast


我們從適用範圍來了解這個操作。


(1)首先dynamic_cast能夠應用於指針轉換。

子類指針轉換成父類指針,成功;

父類指針轉換成子類指針,就分爲兩種情況:

      <a>父類指針p如果真的指向子類對象,那麼轉換時成功的;

      <b>反之,失敗,dynamic_cast返回NULL。


(2)其次dynamic_cast能夠應用與引用之間的轉換(與指針類似)。

子類引用轉換成父類引用,成功;

父類引用轉換成子類引用,就分爲兩種情況:

       <a>父類引用ob,如果真的指向子類對象,那麼轉換時成功的;

      <b>反之,失敗,dynamic_cast,會拋出bad_cast異常


(3)其他將null指針,轉換成任何類型的指針;將任何類型的指針轉換成void*類型的指針。

 

參考代碼:

class CBase
{
protected:
    int m_data;
public:
    virtual void fun(){}
};
class CSub1 : publicCBase
{
protected:
    intm_data_a;
};
class CSub2 : publicCBase
{
protected:
    longm_data_b;
};
//////////////////////////////////////////////////////////////////////////
void test_dynamic_cast()
{
    CBase * pb = newCBase();
    CSub1 * p1 = newCSub1();
 
    charstrTrue[] = "true";
    charstrFalse[] = "false";
    //cast a class toits base class
    CBase * p = dynamic_cast<CBase*>(p1);
    cout<<"dynamic_cast<CBase *>(p1); is ok? "<< ((p != NULL) ? "true" : "false")<<endl;
    //cast a class toits derived class
    CSub1 * pSub1 = dynamic_cast<CSub1*>(pb);
    cout<<"dynamic_cast<CSub1 *>(pb); is ok? "<< ((pSub1 != NULL)? "true" : "false") <<endl;
 
    delete pb;
    delete p1;
    //
    try
    {
        CBase obb;
        CSub1 obsub1;
        CBase & ob1 = dynamic_cast<CBase &>(obsub1);
        CSub1 & ob2 = dynamic_cast<CSub1 &>(obb);
    }
    catch(bad_cast e)
    {
       
    }
   
}



二、Static_Cast


Static_cast可以轉換相關聯的類,可以從子類轉換成父類。也能從父類轉向子類,但是如果轉換的父類指針(或者父類引用)所指向的對象是完整的,那麼是沒有問題;但是如果所指向的對象並不完整,那麼會出現runtime錯誤。

Static_cast相對於dynamic_cast而言,除了能轉換指針和引用,還能應用於任何能夠隱式轉換的情況。比如下面的情況。

void test_static_cast()
{
    float f =1.012;
    int i = static_cast<int>(f);
}



三、Reinterpret_Cast

reinterpret_cast和上面講到的兩個cast,適用範圍更加廣泛。它可以適用於任何類型指針之間的轉換。

該操作不會去進行動態類型或者靜態類型的檢測,它僅僅將值強行賦值過去。從某種意義上對編譯器進行了一種欺騙,同時也帶來了一定的不安全性。所以在使用這個cast的時候,要慎重。下面是這個操作的適用情況:

(1)   Int和指針之間的相互轉換;

(2)   無關聯類指針之間的轉換;

(3)   函數指針之間的轉換

 

下面是這個操作的使用實例:

class A
{
public:
    A(inti):m_data(i){}
    int m_data;
};
class B
{
public:
    B(floatf):m_data(f){}
    floatm_data;
};
class C
{
public:
    C(long long ll):m_date(ll){}
    long long m_date;
};
void test_reinterpret_cast()
{
    A * pa = newA(1);
    B * pb = newB(1.12);
    C * pc = newC(121321312321);
    //
    A * p1 = reinterpret_cast<A*>(pb);
    cout<<"  reinterpret_cast<A *>(pb); is ok?"<< ((p1 != NULL) ? "true": "false") <<endl;
    cout<<p1->m_data<<endl;
    p1 = reinterpret_cast<A*>(pc);
    cout<<"  reinterpret_cast<A *>(pc); is ok?"<< ((p1 != NULL) ? "true": "false") <<endl;
    cout<<p1->m_data<<endl;
 
    //
    delete pa;
    delete pb;
    delete pc;
}

結果:



四、Const_Cast


const_cast如它的名字,它是去除修飾在對象上的constvolatile

 


五、總結


這裏借用more effective c++中的觀點:隱式轉換,在代碼中很難尋找;但是使用C++的這種cast可以輕鬆的找出,代碼中哪裏使用強制轉換等。去除了c語言中轉換之間的惡習,將它們規範成了幾個operator。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章