如何解决我可以在固定大小的假设下拥有一个多态值向量吗?
考虑下面的代码,派生类用函数的变体替换了虚成员函数,但没有添加任何新的成员变量。 Base 和 Derived 的值被添加到一个公共容器 std::vector 中,正如预期的那样,Derived 值被切片。然而,通过将 Derived 值在内存中的表示复制到容器中,该值实际上只是部分切片。
#include <iostream>
#include <vector>
class Base {
public:
Base() = default;
Base(float arg) : a{ arg } {};
virtual float doSomething(float b) const { return a + b; }
float a;
};
class Derived : public Base {
public:
Derived() = default;
Derived(float a) : Base{ a } {};
float doSomething(float b) const { return a - b; }
};
int main()
{
Base b{ 1.0f };
Derived d{ 1.0f };
std::cout << sizeof(b) << "," << sizeof(d) << '\n'; // 8,8
std::vector<Base> v{ b,d }; // d is sliced
std::cout << v[0].doSomething(2.0f) << '\n'; // 3
std::cout << v[1].doSomething(2.0f) << '\n'; // 3 as d was sliced
memcpy(&v[1],&d,sizeof(d)); // copy the representation of d over to v[1]
std::cout << v[1].doSomething(2.0f) << '\n'; // Now -1
}
由于指向虚函数表的指针,值的大小为 8,这是实现上述多态性的方法。 v[1] 的类型总是 Base,所以如果 Derived 添加了一个新的成员函数,就不可能调用它。实际上 v[1] 仍然被切分到 Base,但重新实现了 Derived 的成员函数。
假设 Base 本质上是 POD,但添加了虚拟成员函数,所有这些都是 const,即内存可复制,并且 Derived 仅重新实现这些成员函数:
解决方法
阿米尔的回答正是我需要的。但是,为了完整起见,我现在将填写我提出问题时真正想要的内容。
可以在 std::vector 中存储不同类型的值,只要这些类型本身适当地包装在一个公共类型中,本质上是一种类型擦除。容器内部将有一个固定长度的缓冲区并具有适当的对齐方式,例如使用 std::aligned_storage。然后,您将使用新的布局和带有克隆函数的每种类型的模板来实现复制/移动语义。
一个明显的增强是允许类型过大,使得 unique_ptr 无法容纳缓冲区。从这个角度来看,容器实际上是一个围绕 unique_ptr 的包装器,其中包含了一个小的缓冲区优化。
我计划将其作为自己的练习来实施,如果/有机会,我会编辑此答案。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。