C ++中的多态返回类型

时间:2013-08-27 11:09:30

标签: c++ pointers c++11 reference polymorphism

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

我的情况非常普遍我有几个类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因为然后我将返回一个抽象对象。

任何优选的或创造性的方法来解决这个问题? :)

2 个答案:

答案 0 :(得分:3)

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

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

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

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

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

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

如上所述,第一个解决方案是最简单的。第一个解决方案的成本仅仅是基于性能的,如果您发现它们存在真正的问题,那么这些性能命中并不难解决。因此,我会建议解决方案#1,然后进行分析,看看所涉及的成本是否过高。如果成本很高,请转到解决方案#3,可能在解决方案#2包装器中。

答案 1 :(得分:2)

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

Inf2子类类型的对象应该存储在哪里?何时以及何时删除Inf2的实施。对此的答案通常决定了使用什么样的句柄概念。例如,如果在内存池中分配Inf2实现,则返回Inf2*就可以了。如果您想要单一所有权,也可以使用unique_ptr<Inf2>,但是您无法复制句柄。如果要复制句柄,也可以使用shared_ptr<Inf2>,但是必须小心循环,效率稍差。您还可以创建一个包装类Inf2Handle,它可以执行更复杂的操作,例如写时复制或其他操作。

您提到实现很小,因此内存池可能是最好的架构。

哪个是最佳选择,实际上取决于Inf1Inf2的使用方式。