将基类动态转换为派生对象
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*
才能管理派生类型的对象。如何管理对象本身的生命周期,无论是存储在其他地方,还是使用拥有它们的向量(最好是智能)指针,留作练习。
我正在尝试将派生对象分配给基础对象向量,然后将它们转换回派生对象。虽然我不能做演员。
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*
才能管理派生类型的对象。如何管理对象本身的生命周期,无论是存储在其他地方,还是使用拥有它们的向量(最好是智能)指针,留作练习。