2010-08-20 42 views
1

當我應用指向乘法繼承對象的實例的指針時,dynamic_cast運算符返回零(0)。我不明白爲什麼。動態轉換和多重繼承

層次結構:

class Field_Interface 
{ 
    public: 
    virtual const std::string get_field_name(void) const = 0; // Just to make the class abstract. 
}; 


class Record_ID_Interface 
{ 
    public: 
    virtual bool has_valid_id(void) const = 0; 
}; 


class Record_ID_As_Field 
: public Field_Interface, 
    public Record_ID_Interface 
{ 
// This class behaves as a Field and a Record_ID. 
// ... 
} 


// A demonstration function 
void Print_Field_Name(const Field_Interface * p_field) 
{ 
    if (p_field) 
    { 
    cout << p_field->get_field_name() << endl; 
    } 
    return; 
} 


// A main function for demonstration 
int main(void) 
{ 
    Record_ID_As_Field * p_record_id = 0; 
    p_record_id = new Record_ID_As_Field; 
    if (p_record_id) 
    { 
    // (1) This is the trouble line 
    Print_Field_Name(dynamic_cast<Field_Interface *>(p_record_id)); 
    } 
    return 0; 
} 

我想有Record_ID_As_Field被作爲Field_Interface治療,但也適合在需要Record_ID_Interface

爲什麼上面(1)中的dynamic_cast返回0,我該如何解決這個問題?

我在Windows XP上使用Visual Studion 2008。

注意:爲了簡單起見,我在本例中使用基本指針。實際的代碼使用boost::shared_ptr

+0

沒有理由測試'p_record_id'不爲空,'new'永遠不會返回null。 (我假設這是因爲它是一個片段,但要確保你的公共基類具有虛擬析構函數。) – GManNickG 2010-08-20 18:17:27

+0

我一直認爲動態投射,如果對於向上投射......並且向下投射是隱式的...... – vrdhn 2010-08-20 18:18:43

+0

沒有證據表明你已經實現抽象的方法。你是否? – 2010-08-20 18:21:02

回答

2

注意:爲了簡單起見,我在本例中使用基本指針。實際的代碼使用boost::shared_ptr

這是你的問題就在那裏:你不能dynamic_cast一個shared_ptr<A>shared_ptr<B>因爲這兩種類型實際上並沒有相互關聯的,即使AB是。

幸運的是,在你的問題的具體情況dynamic_cast不應該是必要的,因爲Record_ID_As_Field*應該是隱式轉換爲一個Field_Interface*(因爲一個是從其他來源的)。 shared_ptr實現了將這些隱式轉換提升到各自對象的轉換運算符,因此shared_ptr<Record_ID_As_Field>應隱式轉換爲shared_ptr<Field_Interface>

如果你遺漏了dynamic_cast,它應該工作。

如果你確實需要做一個動態轉換,你可以使用一個special constructor提供由shared_ptr

shared_ptr<Record_ID_As_Field> raf; 
shared_ptr<Field_Interface> fi(raf, dynamic_cast<FieldInterface*>(raf.get()); 

(我不知道如果dynamic_cast失敗,那還有什麼會發生,所以你應該調查處理這種情況的最佳方式。)