2013-06-27 47 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,但只提领一空指针,这不确定的行为后)

相关问题