1

我有一个基类 ( car) 和一个继承基类 ( honda) 的类:

class car
{
    virtual void polymorphic_class()
    {   }
};

class honda : public car
{   };


当我使用以下代码并将我的类转换为空指针时:

list<car> cars;
honda h;
cars.push_back(h);
honda* h_ptr = dynamic_cast<honda*>(&cars.back());
// h_ptr is NULL

为什么?我必须如何正确地投射我的对象?

4

3 回答 3

4

这不起作用的原因是对象切片。里面的对象cars不再honda是 s,而只是汽车。

您需要一个指针或智能指针向量:

list<car*> cars;
honda h;
cars.push_back(&h);
honda* h_ptr = dynamic_cast<honda*>(cars.back());

我实际上会改变设计并使car抽象(纯虚拟析构函数或其他东西)。这样你也会得到一个编译错误。

于 2012-07-05T11:31:54.767 回答
2

多态适用于指针和引用,而不适用于对象实例。

在这种情况下,您的列表包含 type 的对象car,而不是任何派生类型的对象。当您插入 ahonda时,它将复制该car部分并忽略其余部分;这有时被称为切片

对于多态性,您可以使用指针列表:

list<car*> cars {new honda};
honda * h_ptr = dynamic_cast<honda*>(cars.back()); // should be a valid pointer

注意:如果您确实new像我的示例中那样使用分配,请记住delete它们,或者存储智能指针(如std::unique_ptr<car>)而不是原始指针。您还需要一个虚拟析构函数来使用基类指针删除对象。

您可以通过使基类抽象来避免切片问题;如果它包含纯虚函数,则不能实例化该类型的对象,只能实例化覆盖这些函数的派生类型:

class car
{
    virtual ~car() {}
    virtual void do_something() = 0;
};

class honda : public car
{
    void do_something() {}
};

如果您实际上并不想要一个抽象接口(例如,如果您只使用dynamic_cast而不是通过虚拟函数访问派生类功能),那么您可以将析构函数设为纯虚拟;那么派生类将不必显式覆盖任何内容。基类析构函数仍然必须实现,并且由于语言的一个怪癖,该实现必须在类定义之外:

class car
{
    virtual ~car() = 0;
};
inline car::~car() {}

class honda : public car {};

这是一种有点不寻常的方法,因为通过虚函数实现多态性通常更高效、更方便。

于 2012-07-05T11:53:26.577 回答
0

尝试这个

list<car*> cars;
honda *h = new honda();
cars.push_back(h);
honda* h_ptr = dynamic_cast<honda*>(cars.back());

这行得通。

于 2012-07-05T11:33:22.413 回答