我试图将派生对象分配给基础对象的向量,然后将它们转换回派生对象。我虽然无法进行演员表。
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对象,但它仍然失败。
答案 0 :(得分:2)
这不起作用:
void foo(vector<Base> &bases)
{
Base *base;
if (...)
{
base = new Derived;
base->foo = string("hello");
}
bases.push_back(*base)
}
vector<>
包含对象,而不是引用。当push_back
一个被理解为基类型的对象时,只存储适用于基类型的数据(即“切片”)。
相反,请在Base*
中存储shared_ptr<Base>
或vector<>
。
值得注意的是,在上面的代码段中,每当跳过if()
块时,您都会收到访问权限,因为base
永远不会被初始化。
答案 1 :(得分:0)
问题是你不能直接对对象使用多态,你必须使用基础对象的POINTERS然后你可以转换为派生类或直接调用虚方法。
从以下位置更改您的系统:
vector<Base> bases;
到
vector<Base*> bases;
并根据此更新所有代码,一切都将完美运行:)
答案 2 :(得分:0)
您的向量包含Base
类型的Base
个对象。您可能通过复制派生类型来初始化它们;但所有这一切都是复制Base
部分(有些人称之为切片),失去了对原始类型的任何了解。
多态性仅适用于引用或指针;您需要Base*
才能管理派生类型的对象。如何管理对象本身的生命周期,无论是存储在其他地方,还是使用拥有它们的向量(最好是智能)指针,都可以作为练习。