4

我看过一些关于这个问题的帖子,但没有总结我目前情况下的所有选项,并且可能有我没有考虑过的解决方案。

我的情况很一般,我有几个类Inf1 Inf2(更像接口)都有纯虚拟方法。

哪里Inf1有方法

(Inf2& or Inf2* or shared_pointer) foo(/** Some info on how to build the object**/) = 0

(这是问题的一部分)。

在实现时Inf1返回的各种Inf2实现foo

实现相对较小,Inf2所以我不介意按值返回它们,因此它们被复制构造到结果,但我不能声明foo返回,Inf2因为那样我将返回一个抽象对象。

有什么更好的或创造性的方法来解决这个问题?:)

4

2 回答 2

3

所以你有类型Inf1Inf2,它们是相互关联的,并且其中至少有一个包含抽象方法。

您想返回 的一些子实现Inf2,但哪个是在运行时决定的。

这意味着您需要运行时多态性。有 3 种不同的方法可以解决这个问题。

首先,您可以返回一个指针——可能是一个智能指针,例如unique_ptr,指向公共接口。这需要免费的存储(堆)分配,但使所有权明确,并且是最简单的答案。

其次,您可以编写一个类型擦除对象,该对象公开接口的非virtual版本Inf2,并转发到一些内部细节。这些内部细节最终将使用某种智能指针或第三种解决方案。这里的好处是你可以隐藏你管理内存的方式,并简单地用廉价的移动暴露值语义。缺点是有很多样板。

第三,您可以在一组类型上使用类似 a 的东西boost::variantunion以防止访问错误的类型。虽然boost不能直接使用,但可以模仿设计。这个想法是你有一些本地存储,你可以在其中放置新的数据,除了较大的对象,你可以使用智能指针代替。与第二种解决方案不同,您支持的类型集在您的类型中明确列出。boost这是最难的解决方案(如果您至少无权访问),并且要求您拥有一组固定的(在编译时)实现Inf2,所有用户Inf1都必须拥有完整的详细信息。

如前所述,第一个解决方案是最简单的。第一个解决方案的成本仅仅是基于性能的,如果你发现它们是真正的问题,那么这些性能问题在事后就不难解决。所以我会建议解决方案#1,然后分析一下所涉及的成本是否太高。如果成本很高,请转到解决方案#3,可能在解决方案#2 包装器中。

于 2013-08-27T13:19:16.077 回答
2

您的问题实际上是关于内存管理的。的多态子类Inf2可以是任意大的,并且最大的在编译时是未知的,所以你不能用自动存储持续时间来存储它们,因此它们不能按值返回——所以你需要以某种方式为它们管理内存回报最少

子类类型的对象Inf2应该存储在哪里?以及何时何地应该Inf2删除的实现。这个问题的答案通常会决定使用什么样的句柄概念。例如,如果您在内存池中分配 Inf2 实现,那么返回Inf2*就可以了。unique_ptr<Inf2>如果要进行单一所有权,也可以使用,但不能复制句柄。如果要复制句柄也可以使用shared_ptr<Inf2>,但必须注意循环,并且效率略低。您还可以创建一个包装类Inf2Handle来执行更复杂的操作,例如写时复制或其他操作。

您提到实现很小,所以也许内存池是最好的架构。

哪个是最佳选择实际上取决于如何使用Inf1以及如何Inf2使用的大局。

于 2013-08-27T12:50:55.603 回答