管理指向派生对象的指针集合的最佳方式
Best way to manage a collection of pointers to derived objects
我是来自 c# 的 c++ 新手。以下代码不起作用,我不确定它需要什么。任何帮助我了解它为什么不起作用以及它应该进行哪些适当更改的见解将不胜感激。
// GamePlayScreen derives from ScreenBase
std::unique_ptr<GameplayScreen> m_game(new GameplayScreen());
// MenuScreen derives from ScreenBase
std::unique_ptr<MenuScreen> m_menu(new MenuScreen());
// PauseScreen derives from ScreenBase
std::unique_ptr<PauseScreen> m_pause(new PauseScreen());
std::vector<std::unique_ptr<ScreenBase>*> screens;
screens.push_back(&m_game); // this gets the error
我收到编译错误:
C2284"无法将参数 1 从 'std::unique_ptr<_Ty> *' 转换为 'std::unique_ptr<_Ty> *&&'
如果我注释掉最后一行,它可以很好地编译。
基本上,我希望有一个派生项的集合(或者更确切地说是指向它们的指针)。我已经尝试了各种"指向和/或引用"参数的方法以及建立 T 的各种方法vector<T>
但解决方案让我无法找到。
我读了很多:
。你可能想要shared_ptrs...
我鼓励人们在不确定时默认unique_ptr
。 在没有内存所有权设计的情况下降低shared_ptr
正是导致循环内存泄漏的原因。
是的,您也可以使用 unique_ptr
创建循环内存泄漏。 然而,我的经验是,当使用unique_ptr
时,它会鼓励设计人员了解谁拥有什么,随着设计的发展,使循环内存泄漏的可能性降低,并且在发生时更容易调试。
如果在这个设计过程中,设计师发现共享所有权语义实际上是需要的,那么一定要达到shared_ptr
(可能weak_ptr
打破这些循环)。
最后,尽快将原始指针绑定到智能指针。 以下是遵循最佳实践的OP问题的可编译草图:
#include <type_traits>
#include <utility>
#include <memory>
#include <vector>
// A general purpose factory function for unique_ptrs
// Feel free to make this factory function more specific to your domain
template <class T, class ...Args>
typename std::enable_if
<
!std::is_array<T>::value,
std::unique_ptr<T>
>::type
make_ScreenParts(Args&& ...args)
{
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
// Your class hierarchy
struct ScreenBase
{
// Don't forget to make your destructors virtual
virtual ~ScreenBase() = default;
};
// Future-proof your code with typedef's
// If / when you need to switch smart pointer types
// or container types, you'll thank yourself
typedef std::unique_ptr<ScreenBase> ScreenPtr;
typedef std::vector<ScreenPtr> ScreenContainer;
struct GameplayScreen
: public ScreenBase
{
};
struct MenuScreen
: public ScreenBase
{
};
struct PauseScreen
: public ScreenBase
{
};
int main()
{
// raw pointers never exposed here...
ScreenContainer screens;
screens.push_back(make_ScreenParts<GameplayScreen>());
}
这里没有要验证的编译器,但我相信你可以:
// GamePlayScreen derives from ScreenBase
std::shared_ptr<GameplayScreen> m_game(new GameplayScreen());
// MenuScreen derives from ScreenBase
std::shared_ptr<MenuScreen> m_menu(new MenuScreen());
// PauseScreen derives from ScreenBase
std::shared_ptr<PauseScreen> m_pause(new PauseScreen());
std::vector<std::shared_ptr<ScreenBase>> screens;
screens.push_back( m_game );
就像@cheers和hth-alf说的那样,你可能想要共享指针。
尝试更改最后两行,如下所示:
std::vector<std::unique_ptr<ScreenBase>> screens;
screens.push_back(std::move(m_game));
我删除了星号,因为您可能想要一个unique_ptr
向量,而不是指向unique_ptr
的指针向量。此外,顾名思义,unique_ptr
意味着一次只能有一个unique_ptr
拥有所有权,因此您需要明确std::move
它才能转让所有权。
使用 shared_ptr
而不是 unique_ptr
,因为您将从许多位置引用这些屏幕对象。
有这样一种情况,即您想管理具有特定类型的各种屏幕,但也要将另一个屏幕列表作为基本类型,以便您可以在所有屏幕上执行某些操作,而不必知道特定类型屏幕的详细信息。
我认为在这种情况下,您只需要一个原始指针:
// GamePlayScreen derives from ScreenBase
std::unique_ptr<GameplayScreen> m_game(new GameplayScreen());
// MenuScreen derives from ScreenBase
std::unique_ptr<MenuScreen> m_menu(new MenuScreen());
// PauseScreen derives from ScreenBase
std::unique_ptr<PauseScreen> m_pause(new PauseScreen());
std::vector<ScreenBase*> screens;
screens.push_back(&*m_game);
您只需要注意,如果您破坏屏幕,不要让屏幕中的指针悬空。
- 互斥指针的集合
- MPI 集合通信中的指针分配
- 保留计时器集合(对象与指针)的最佳方法
- 如何让集合 in C++过滤掉指向相同值的不同指针
- 集合中的智能指针多态性
- 重载指向集合的指针的开始/结束是否是个好主意
- C++基类指针、集合类
- Boost:当缺少类型时,如何通过基指针序列化/反序列化泛型类型集合
- C++ 创建指向两个相关矢量集合中的对象的指针集合
- 将指向派生类实例的指针集合视为父类
- 管理指向派生对象的指针集合的最佳方式
- 指针集合和添加对象
- C++指针集合类,便于通信
- 更好的std::在指针集合上查找,并将取消引用的值与常量引用值进行比较
- 影响指针集合排序的因素(具体示例)
- 设置不存储指针集合
- 从基类指针集合调用非虚成员函数
- 无法在 CLI C++维护指针集合
- 从指针集合中快速检索特定对象
- 为什么empty set::emplace()将元素插入指针集合?