将基类动态转换为派生对象

dynamic casting of base to derived objects

我正在尝试将派生对象分配给基础对象向量,然后将它们转换回派生对象。虽然我不能做演员。

struct Base
{
    string foo;
    virtual ~Base() {}
};

struct Derived : Base
{
    string bar;
};

我有一个函数可以修改基本元素的向量。根据某些条件,它可能会创建派生对象而不是基础对象并将其推送到向量上:

void foo(vector<Base> &bases)
{
    Base *base;
    if (...)
    {
        base = new Derived;
        base->foo = string("hello");
    }
    bases.push_back(*base) 
}

然后我将一个向量传递给该函数并尝试获取内容。

vector<Base> bases;
foo(bases);

for (auto it = bases.begin(); it != bases.end(); ++it)
{
    Base *base = &(*it);
    Derived *derived = dynamic_cast<Derived*>(base); 
    // derived == nullptr
}

我在这里错过了什么?如果我尝试将 foo 作为 Base 对象访问,它会工作,但是当我尝试动态转换为 Derived 对象时,它会失败,尽管它已在 foo(vector<Base> &bases) 函数中创建为 Derived 对象。

这行不通:

void foo(vector<Base> &bases)
{
    Base *base;
    if (...)
    {
        base = new Derived;
        base->foo = string("hello");
    }
    bases.push_back(*base) 
}

vector<> 包含对象,而不是引用。当您 push_back 一个被理解为基本类型的对象时,仅存储适用于基本类型的数据(即 "sliced.")。

相反,将 Base*shared_ptr<Base> 存储在 vector<> 中。

同样值得注意的是,在上面的代码片段中,只要跳过 if() 块,您就会遇到访问冲突,因为 base 从未被初始化。

问题是你不能直接对对象使用多态性,你必须使用基础对象的指针,然后你可以转换为派生的类或直接调用虚拟方法。

更改您的系统:

vector<Base> bases;

vector<Base*> bases;

并以此为基础更新所有代码,一切都会完美运行:)

您的向量包含 Base 个对象,类型为 Base。您可能已经通过复制派生类型来初始化它们;但所做的只是复制 Base 部分(有些人称之为 切片 ),失去了对原始类型的任何了解。

多态性仅适用于引用或指针;您需要 Base* 才能管理派生类型的对象。如何管理对象本身的生命周期,无论是存储在其他地方,还是使用拥有它们的向量(最好是智能)指针,留作练习。