BOOST和C++:似乎无法使多态性起作用

dub*_*wer 2 c++ boost ptr-vector

我正在使用ptr_vector来存储"形状".我试图用派生的形状类来填充它,比如"圆圈",每当我试图向下转换它们时,我都会变坏.

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");
}
Run Code Online (Sandbox Code Playgroud)

And*_*owl 6

问题是你shape的类型是一个对象Shape,而不是对(动态)类型的对象的引用Circle.

多态性仅适用于引用或指针.当将对象作为处理并从派生类的对象复制构造或移动构造基类的对象时,你得到的就是切片(绝对不是你想要的东西).

试试这个:

BOOST_FOREACH(Shape& shape, shapes)
//                 ^
Run Code Online (Sandbox Code Playgroud)

可能使用引用也是有意义的const- 因为你不打算修改循环中引用的对象,所以:

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

    // ...
}
Run Code Online (Sandbox Code Playgroud)

另请注意,C++ 11具有基于范围的for循环,这种循环BOOST_FOREACH已经过时了.因此,如果C++ 11是一个选项,你可以写:

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

    // ...
}
Run Code Online (Sandbox Code Playgroud)

这就是说,有必要指出(正如Chad在评论中所做的那样)你不需要在这里执行动态向下转换,因为它print()是一个虚函数.做的时候:

shape.print();
Run Code Online (Sandbox Code Playgroud)

Circle::print()如果引用的对象Shape是实例,则将调度函数调用Circle.