2015-04-20 38 views
4

這是我在這個網站的第一個問題,可以隨意突出與我的字的選擇,問題結構等的dynamic_cast和多態性

最近出現任何問題,我開始與多態性處理時使用dynamic_cast,和我已經讀取dynamic_cast不會創建該類的另一個實例,而是創建另一個指向該對象的指針實例。

在測試dynamic_cast時,我遇到了這個問題。下面是代碼:

//main.cpp 

#include <iostream> 

class Base{ 
public: 
    int BaseNum; 
    virtual void BaseFunction(){}; 
}; 

class Derived : public Base{ 
public: 
    int DerivedNum; 
    virtual void DerivedFunction(){}; 
}; 

int main(){ 

    Base * ptrBase = new Base; 
    ptrBase->BaseNum = 0; 
    Derived * ptrDerived = dynamic_cast<Derived *>(ptrBase); 
    ptrDerived->DerivedNum = 1; 

    std::cout << ptrBase->BaseNum << ptrDerived->DerivedNum << std::endl; 

    system("pause"); 
    return 0; 
} 

程序在該行崩潰:

ptrDerived->DerivedNum = 1; 

調試時,它說:「無法讀取內存」。我的結論是,如果原始內存分配是爲層次結構中較高的類保留的,我不能沮喪,但我認爲我可能是錯的。

代碼出錯了?

回答

7

dynamic_cast在指定的對象中查找請求的類類型,並返回指向該對象部分的指針/引用。如果找不到,則會爲指針強制轉換返回NULL,並且會爲引用強制轉換拋出異常。在你的例子中,它失敗了,因爲ptrBase沒有指向一個對象,該對象是Derived類的一個實例,所以對象內沒有Derived部分返回一個指針,所以它返回NULL。你需要改變這一點:

Base * ptrBase = new Base; 

爲了這個:

Base * ptrBase = new Derived; 
+0

感謝澄清,所以基本上dynamic_cast不會添加任何內存分配。 – Ediac

+0

沒有分配,只是一個指向現有對象內不同內存地址的指針。 –

+1

@DiegoLiu:'dynamic_cast'說:「嘿,看看這是不是派生的,如果是的話,給我一個指向它那邊的指針 –

3

你的問題是你正在使用動態倒退。

如果你沒有

Base *ptrBase = new Derived ; 

然後,它會工作。

衍生出來的基地。 基地不是派生的。

+0

你已經走出了正確的答案。 –

1

在你的示例代碼,您創建的Base一個新實例:

Base * ptrBase = new Base; 
ptrBase->BaseNum = 0; 
Derived * ptrDerived = dynamic_cast<Derived *>(ptrBase); 

由於Derived是一個超集Base,但基數只是Derived的一個子集,因此您無法將ptrBase指向的對象定位爲bein g Derived,因爲它比Derived'小'。

如果,另一方面,你寫

Base * ptrBase = new Derived; 
ptrBase->BaseNum = 0; 
Derived * ptrDerived = dynamic_cast<Derived *>(ptrBase); 

那麼一切都很好,因爲現在的目標指向ptrBaseDerived

隨着dynamic_cast,這是由程序員來確保轉換成功。

+1

編譯器確保轉換是* legal *。程序員必須確保轉換是*成功*,因爲編譯器無法在編譯時驗證。 –

+0

@RemyLebeau感謝您的評論,我編輯了措辭。 – MicroVirus