拥有所有从同一个基类派生的类实例集合的最佳方法是啥?

Posted

技术标签:

【中文标题】拥有所有从同一个基类派生的类实例集合的最佳方法是啥?【英文标题】:What's the best way to have a collection of instances of classes all derived from the same base class?拥有所有从同一个基类派生的类实例集合的最佳方法是什么? 【发布时间】:2012-03-13 05:38:34 【问题描述】:

我有一个类的集合,这些类都派生自一个共同的基础。我需要一个集合(可能是list)来保存各种类型的派生类的实例。类操作将调用集合中实例的虚拟方法。当然,我不能使用list<Base>,因为按值保存基类会切片派生类。

显而易见的解决方案是使用list<Base*> 并将其包装在具有复制构造函数、析构函数等的类中。基类将有一个虚拟的duplicate 函数,该函数在每个派生类中被重载,以返回指向该派生类的复制构造的新实例的指针。析构函数必须遍历列表和delete 每个项目。

如果有 Boost 方法可以做到这一点,那很好。我已经在使用 Boost 了。在我看来,使用 Boost 的共享指针将是最好的方法。管理共享引用计数会有开销,但这必须比指针情况下所需的分配/复制便宜。但是,这意味着集合的副本将产生相同的实例,并且更改一个副本将更改另一个副本。

我还不完全知道这段代码将如何实际使用。所以我不确定共享副本语义是否会成为问题。我认为副本不会很普遍,它们只需要谨慎处理即可。

还有其他方法吗?

【问题讨论】:

如果对象不重,则首先尝试 boost 指针容器,否则尝试使用 boost::shared_ptr 的 STL 容器(向量、列表等) 【参考方案1】:

向Boost.PointerContainer问好。默认情况下,当您复制容器时,这些提供深度复制语义(但是,这是可定制的)。请注意,您需要在适当的命名空间中为您的抽象基类实现一个免费的new_clone 方法。

另外,作为旁注,使用std::vector作为您的首选容器。

另一个注意事项,不要将container<Base*> 包装起来,而是将Base* 包装在您猜对了的智能指针中。如果您不想共享所有权,C++11 提供unique_ptrunique_ptr 只允许移动它,你不能复制它。

【讨论】:

我应该猜到 Boost 有一个专门解决这个问题的类!使用此解决方案,我将需要一个空对象类型。我可能会为此使用基类。 @David:另见this related question wrt new_clone @DavidSchwartz:你确实不需要需要一个空对象类型。 boost::ptr_vector 专门设计为默认不允许空指针,可以使用 nullable 进行调整,请参阅 the tutorial @MatthieuM.:谢谢!我仍然认为我想要一个 null 对象类型,因为 null 对象很少见,并且只在它们上调用知道做正确事情的方法比必须在任何地方检查 null 更容易。但是我这样做很好,因为我认为这是最好的,而不是因为容器强迫我这样做。 @DavidSchwartz:如果它对您的应用程序有意义,那么我同意 null 对象类型可以让您的生活更轻松。

以上是关于拥有所有从同一个基类派生的类实例集合的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

将指针从派生类转换为基类的最佳方法

Typescript派生类和抽象类

在类库项目的基类中定义 HttpClient 实例的最佳方法是啥?

将派生自基类的类的实例传递给函数

基类和派生类

不是抽象类的基类不是好基类