具有多态数据的容器的常见实现是什么
What are common implementations for containers with polymorphic data?
假设我创建了一个抽象类Entity,然后创建了它的多个子类,每个子类都有它的参数和函数,但由于Entity,共享了一个公共接口。这是迄今为止面向对象编程中最常见的例子。
当我创建一个Entity值的向量并告诉它为N个元素保留(确保容量而不调整大小)时,内部会发生什么。如果大小可以是任何值,它是如何知道大小的?公共部分是否存储在向量中,然后是指向子类特定部分的指针?如果是这样的话,指针最终会在堆中声明到哪里?这将对缓存性能极为不利。
最后,这与POD和非POD类型有任何关系吗?
如果向量包含Entity
值,则它包含类型为Entity
的值,而不是任何子类。由于Entity
是抽象的,因此不能实例化这样的向量。
如果你想要多态性,你就必须存储指向存储在其他地方的对象的指针,或者如果你想让向量像管理元素一样管理它们的生存期,就必须存储智能指针。
一旦抽象类开始发挥作用,POD就会直接退出窗口。你正在通过指针处理一切。你不在乎对象的大小,因为它不是对象的向量,而是指向对象的指针的向量。
如果向量"拥有"内存(听起来像你的情况),那么代码看起来是这样的。。。
// Declaration
std::vector <Entity *> ent_vector;
// Inserting into the vector
ent_vector.push_back(new EntityImpl());
// In a destructor somewhere...
for (std::vector<Entity *>::iterator i = ent_vector.begin(); i != ent_vector.end(); ++i)
{
delete *i;
}
C++中没有明确支持这类事情。您必须(正如Mike的回答中所解释的那样)通过指针访问多态对象,以确定多态行为。这意味着您必须将指针存储在容器中。如果像往常一样,您希望容器也能管理对象的生存期,那么您应该使用unique_ptr
s。
你可以沿着的路线创建自己的小多态容器
template<typename AbstractType>
class poly_vector
: std::vector<std::unique_ptr<AbstractType>>
{
typedef std::vector<std::unique_ptr<AbstractType>> base;
public:
using base::begin; // public access
using base::end; // to some vector
using base::size; // functionality
poly_vector() = default; // default ctor
poly_vector(poly_vector&&) = default; // move, but
poly_vector(poly_vector const&) = delete; // no copy
// add another object at the end
template<typename DerivedType, typename...Args>
typename std::enable_if<std::is_base_of<AbstractType,DerivedType>::value>::type
emplace_back(Args&&..args)
{
base::emplace_back(new DerivedType(std::forward<Args>(args)...);
}
};
然而,begin()
指向的对象又是指针(实际上是unique_ptr
s),因此访问多态对象的语义有点不寻常。此外,emplace_back
的语义是不寻常的:您必须像在myvec.emplace_back<Dervied>(arg1,arg2);
中一样明确地提供DerivedType
作为模板参数
当然,您可以详细阐述以上想法,包括避免双重取消围栏的迭代器类型,以及完全分配器支持等。。。
- 如果没有malloc,链表实现将失败
- 如何在c++中实现处理器调度模拟器
- 如何在c++中使用引用实现类似python的行为
- 实现无开销push_back的最佳方法是什么
- 使用简单类型列表实现的指数编译时间.为什么
- 如何在BST的这个简单递归实现中消除警告
- 实现一个在集合上迭代的模板函数
- 我应该实现右值推送功能吗?我应该使用std::move吗
- 如何正确实现和访问运算符的各种自定义枚举器
- C++Union/Struct位域的实现和可移植性
- 这个极客对极客的trie实现是否存在内存泄漏问题
- 在c++中实现LinkedList时,应出现未处理的错误
- 为左值和右值的包装器实现C++范围
- 使用模板进行堆栈实现; "name followed by :: must be a class or namespace"
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 使用动态分配数组和 realloc() 实现一些常见的 ADT
- 具有多态数据的容器的常见实现是什么
- C++模板类专用化:为什么需要重新实现常见方法
- 如何实现 STL 风格的迭代器并避免常见的陷阱
- 内存池背后的常见实现细节是什么?