BOOST 和 C++:似乎无法让多态性发挥作用



我正在使用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");
}

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

多态性仅适用于引用或指针。当将对象视为,并从派生类的对象复制基类的构造对象或移动基类的构造物体时,您得到的是切片(绝对不是您想要的)。

试试这个:

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);
    //     ^^^^^^                                  ^^^^^^
    // ...
}

也就是说,有必要指出(正如Chad在评论中所做的那样),您不需要在这里执行动态下变频,因为print()是一个虚拟函数。执行时:

shape.print();

如果Shape引用的对象是Circle的实例,则函数调用将被分派到Circle::print()

此外,您没有正确使用dynamic_cast。如果您dynamic_cast引用,而对象实际上不属于要将其强制转换到的类,则强制转换将抛出std::bad_cast。它不会返回null,因为不存在具有null地址的引用。因此,以下是正确的方法:

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

(实际上,您可以使用&r == NULL来引用r,但只有在取消引用具有未定义行为的空指针之后。)

相关内容

  • 没有找到相关文章

最新更新