简体   繁体   English

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

[英]BOOST and C++: can't seem to get polymorphism to work

I'm using ptr_vector to store "shapes". 我正在使用ptr_vector来存储“形状”。 I'm trying to fill it with derived shape classes, such as "circles", and every time I try to downcast them I get bad cast. 我试图用派生的形状类(例如“圆”)填充它,并且每次我尝试将它们压低时,我都会感到不舒服。

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");
}

The problem is that your shape is an object whose type is Shape , and not a reference to an object whose (dynamic) type is Circle . 问题在于您的shape是类型为Shape的对象,而不是对(动态)类型为Circle的对象的引用。

Polymorphism only works with references or pointers . 多态只适用于引用或指针 When treating objects as values and copy-construct or move-construct objects of a base class from objects of a derived class, what you get is slicing (definitely not something you want). 将对象视为并从派生类的对象中复制基类的对象时,所得到的就是切片 (绝对不是您想要的)。

Try this instead: 尝试以下方法:

BOOST_FOREACH(Shape& shape, shapes)
//                 ^

It would also make sense to use a reference to const , probably - since you are not going to modify the referenced object inside the loop, so: 使用对const的引用可能也很有意义-因为您不会在循环内修改引用的对象,所以:

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

    // ...
}

Also notice, that C++11 has range-based for loops, which make BOOST_FOREACH kind of obsolete. 还要注意,C ++ 11具有基于范围的for循环,这使BOOST_FOREACH有点过时了。 So if C++11 is an option, you could write: 因此,如果可以选择C ++ 11,则可以编写:

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

    // ...
}

This said, it makes sense to point out ( as Chad does in the comments ) that you do not need to perform a dynamic downcast here, since print() is a virtual function. 也就是说,有必要指出( 就像Chad在评论中一样 ),因为print()是一个虚函数,所以您不需要在此处执行动态向下转换。 When doing: 进行时:

shape.print();

The function call will be dispatched to Circle::print() if the object referenced by Shape is an instance of Circle . 如果Shape引用的对象是Circle的实例,则该函数调用将调度到Circle::print()

Also, you're not using dynamic_cast correctly. 另外,您没有正确使用dynamic_cast。 If you dynamic_cast a reference, and the object does not actually belong to the class you're casting it to, then the cast throws std::bad_cast . 如果您dynamic_cast一个引用,并且该对象实际上并不属于您要对其进行强制转换的类,则强制转换会抛出std::bad_cast It does not return null because there's no such thing as a reference with a null address. 它不返回空值,因为不存在带有空地址的引用。 So here's the correct way: 所以这是正确的方法:

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

(You can actually have a reference r with &r == NULL , but only after dereferencing a null pointer, which has undefined behavior.) (实际上,您可以使用&r == NULL引用r ,但是只有在取消引用具有未定义行为的空指针之后才可以。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM