2013-06-27 48 views
2

我正在使用ptr_vector來存儲「形狀」。我試圖用派生的形狀類來填充它,比如「圈子」,每次我試圖貶低它們時,我都會變得糟糕。BOOST和C++:似乎無法獲得多態性工作

class Shape 
{ 
public: 
    virtual ~Shape() {}; 
    virtual void print() { std::cout << "shape" << std::endl; }; 
}; 

class Circle : 
    public Shape 
{ 
public: 
    void print() { std::cout << "circle" << std::endl; }; 
}; 

int main() 
{ 
    boost::ptr_vector<Shape> shapes; 
    shapes.push_back(new Circle); 

    BOOST_FOREACH(Shape shape, shapes) 
    { 
     Circle& tempCircle = dynamic_cast<Circle&>(shape); 
     if(&tempCircle != NULL) 
      tempCircle.print(); 
    } 

    system("PAUSE"); 
} 

回答

6

的問題是,你是shape一個對象,其類型爲Shape,而不是一個對象,其(動態)型是Circle的參考。

多態性僅適用於參考或指針。當將對象看作的值並從派生類的對象複製構造或移動構建基類的對象時,您得到的結果是slicing(絕對不是您想要的)。

試試這個:

BOOST_FOREACH(Shape& shape, shapes) 
//    ^

這也將是有意義的使用參考const,可能 - 因爲你不打算修改循環中引用的對象,所以:

BOOST_FOREACH(Shape const& shape, shapes) 
//     ^^^^^^ 
{ 
    Circle const& tempCircle = dynamic_cast<Circle const&>(shape); 
    //  ^^^^^^         ^^^^^^ 

    // ... 
} 

另請注意,C++ 11具有基於範圍的for循環,這使得BOOST_FOREACH種類已過時。所以,如果C++ 11是一個選項,你可以寫:

for (auto const& shape : shapes) 
{ 
    Circle const& tempCircle = dynamic_cast<Circle const&>(shape); 
    //  ^^^^^^         ^^^^^^ 

    // ... 
} 

這就是說,它是有道理指出(as Chad does in the comments),你不需要在這裏進行動態垂頭喪氣,因爲print()是一個虛擬的功能。當這樣做的:

shape.print(); 

函數調用將被分派到Circle::print()如果Shape引用的對象是Circle一個實例。

+0

還要注意,因爲'打印() '是一個虛函數,在這種情況下'dynamic_cast'是不必要的。 – Chad

+0

@查德:哦,對了,我錯過了那部分。我會編輯,謝謝:) –

+0

@Chad:當我用於(自動常量&形狀:形狀),當我嘗試調用shape.print()時,它表示該對象具有與成員不兼容的類型限定符函數:( – dubesinhower

0

此外,您沒有正確使用dynamic_cast。如果您dynamic_cast一個引用,並且該對象實際上不屬於您要投射到的類,則投射投擲std::bad_cast。它不會返回null,因爲不存在空值地址的引用。因此,這裏的正確方法:

Circle* tempCircle = dynamic_cast<Circle*>(&shape); 
if(tempCircle != NULL) 
    tempCircle->print(); 

(實際上,你可以有一個參考r&r == NULL,但只提領一空指針,這不確定的行爲後)

相關問題