父類和子類之間的轉換問題

bzhxuexi發表於2013-11-21

 有兩個問題:(1)子類物件可以轉化為父類物件嗎?

                       (2)父類物件可以轉化為子類物件嗎?

------------------------------------------------------------------------------------------------------------------------------------

java:

        第(1)個問題應該都不陌生,也沒什麼好探討的,肯定可以,因為在多型中經常用到。

               如:class  Father

                       {

                       };

                       calss Son extends  publc  Father

                       {   

                       };

                      Father  f  =   new  Son();  //父類引用指向子類物件

                            其中,new  Son()表示在在堆中分配了一段空間來存放類Son中的資料,

                            並返回一個Son的物件,並賦值給Father的引用f,即f指向子類的物件,

                           此時,子類的物件並沒有定義一個名字。

                           定價於:

                           Son  s  =   new  Son();

                            Father  f  =  s;

---------------------------------------------------------------------------------

                     第(2)個問題:一般情況下,父類物件是不可以強制轉化為子類物件的,

                      如:

                       class  Father

                       {

                       };

                       calss Son : publc  Father

                       {   

                       };

                       Son   s  =   new   Father();  //error

                        因為,子類除了從父類繼承一些東西外,它還增加了一些自己的東西,也就是說,

                       子類物件一般都比父類物件包含更多的東西。這樣的話,子類如果訪問子類新增的內容,

                         而這些內容父類並沒有,所以就會報錯。

                     

                   但是,如果前提是:此父類物件已經指向了此子類物件,就可以轉換。

                  如:

                      Father  f  =   new  Son();  //父類引用指向子類物件

                      Son   s2  =  (Son)f;  //可以

                      因為,子類強制轉換為父類物件時,並沒有實際丟失它原有記憶體空間(比父類多的那些部分)

                                只是暫時不可訪問,所以能再轉回來。

                   一般在前面加一條判斷語句 if(father instanceof Son);防止報ClassCastExcept異常。

                  如:

                        Father  f  =   new  Son();  //父類引用指向子類物件

                        if(father instanceof Son)

                       {

                                 Son   s2  =  (Son)f;

                      }

    結論:(1)子類物件可以轉化為父類物件

              (2)一般不可以,但是如果此父類已經指向了此子類物件,可以


C++:

       但在C++語言怎麼實現呢?一個指向子類的父類變數怎樣才能通過轉換賦值給一個子類物件變數?      

        可以用dynamic_cast  。

    dynamic_cast的用法:

              dynamic_cast < type-id > ( expression )
               該運算子把expression轉換成type-id型別的物件。Type-id必須是類的指標、類的引用或者void*;
             如果type-id是類指標型別,那麼expression也必須是一個指標,如果type-id是一個引用,

            那麼expression也必須是一個引用。
             dynamic_cast運算子可以在執行期決定真正的型別。如果downcast是安全的(也就說,如果基類指標

            或者引 用確實指向一個派生類物件)這個運算子會傳回適當轉型過的指標。如果downcast不安全,

             這個運算子會傳回空指標(也就是說,基類指標或者引用沒有指向一個派生類物件)。
             dynamic_cast主要用於類層次間的上行轉換和下行轉換,還可以用於類之間的交叉轉換。
             在類層次間進行上行轉換時,dynamic_cast和static_cast的效果是一樣的;
             在進行下行轉換時,dynamic_cast具有型別檢查的功能,比static_cast更安全。

                

                   在進行下行轉換時,dynamic_cast具有型別檢查的功能,比static_cast更安全。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class B
{
public:
    int m_iNum;
    virtual void foo();
};
class D:public B
{
public:
    char *m_szName[100];
};
void func(B *pb)
{
    D *pd1 = static_cast<D *>(pb);
    D *pd2 = dynamic_cast<D *>(pb);
}
           在上面的程式碼段中,如果pb指向一個D型別的物件,pd1和pd2是一樣的,並且對這兩個指標執行D型別的任何操作都是安全的;
但是,如果pb指向的是一個B型別的物件,那麼pd1將是一個指向該物件的指標,對它進行D型別的操作將是不安全的(如訪問m_szName),
而pd2將是一個空指標。
       如果pb指向一個D型別的物件,pd1和pd2是一樣的,並且對這兩個指標執行D型別的任何操作都是安全的;
但是,如果pb指向的是一個B型別的物件,那麼pd1將是一個指向該物件的指標,對它進行D型別的操作將是不安全的(如訪問m_szName),
而pd2將是一個空指標
               


相關文章