我目前正在尝试建立一个非常基本的实体组件系统。 为此,我定义了以下类:
class Component
{
public:
virtual ~Component() {}; // Ensure polymorphic behavior with a virtual destructor
};
class TransformComponent : public Component
{
glm::vec2 position = {0.0f, 0.0f};
float rotation = 0.0f;
float scale = 1.0f;
};
using identifier = uuids::uuid;
class Entity {
private:
identifier id;
bool isActive = true;
std::string name = "new entity";
std::vector<std::unique_ptr<Component>> components;
public:
Entity() : isActive(true), id( UUID::get()), name("NEW") {};
~Entity() = default;
// Disable copying
Entity(const Entity&) = delete;
Entity& operator=(const Entity&) = delete;
// Define move constructor and move assignment
Entity(Entity&& other) noexcept;
Entity& operator=(Entity&& other) noexcept;
template<typename T>
T* GetOrAdd() {
static_assert(std::is_base_of<Component, T>::value, "T must be derived from Component");
for (auto& comp : components) {
if (auto result = dynamic_cast<T*>(comp.get())) {
return result;
}
}
auto newComp = std::make_unique<T>();
T* result = newComp.get();
components.push_back(std::move(newComp));
return result;
}
当我尝试将实体作为 std::unique_ptr 添加到另一个类时,如下所示:
class Scene {
public:
Scene(std::string sceneName, bool isEditorMode);
~Scene();
private:
std::unique_ptr<Entity> ent = std::make_unique<Entity>();
}
我收到以下错误:
D:\Projects\searchengineproject\vocabulary\game\src\rendering\HierarchyPanel.cpp: In constructor 'gl3::HierarchyPanel::HierarchyPanel()':
D:\Projects\searchengineproject\vocabulary\game\src\rendering\HierarchyPanel.cpp:9:52: error: use of deleted function 'gl3::Scene& gl3::Scene::operator=(const gl3::Scene&)'
9 | currentScene = *GlobalHelper::GetScenes()[0];
| ^
In file included from D:\Projects\searchengineproject\vocabulary\game\src\rendering\HierarchyPanel.h:4,
from D:\Projects\searchengineproject\vocabulary\game\src\rendering\HierarchyPanel.cpp:1:
D:/Projects/searchengineproject/vocabulary/game/src/entities/Scene.h:21:11: note: 'gl3::Scene& gl3::Scene::operator=(const gl3::Scene&)' is implicitly deleted because the default definition would be ill-formed:
21 | class Scene {
| ^~~~~
D:/Projects/searchengineproject/vocabulary/game/src/entities/Scene.h:21:11: error: use of deleted function 'std::unique_ptr<_Tp, _Dp>& std::unique_ptr<_Tp, _Dp>::operator=(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = gl3::Entity; _Dp = std::default_delete<gl3::Entity>]'
In file included from D:/Program Files/CLion 2022.3.3/bin/mingw/lib/gcc/x86_64-w64-mingw32/11.2.0/include/c++/bits/locale_conv.h:41,
from D:/Program Files/CLion 2022.3.3/bin/mingw/lib/gcc/x86_64-w64-mingw32/11.2.0/include/c++/locale:43,
from D:/Program Files/CLion 2022.3.3/bin/mingw/lib/gcc/x86_64-w64-mingw32/11.2.0/include/c++/bits/fs_path.h:37,
from D:/Program Files/CLion 2022.3.3/bin/mingw/lib/gcc/x86_64-w64-mingw32/11.2.0/include/c++/filesystem:45,
from D:/Projects/searchengineproject/vocabulary/game/src/rendering/Texture.h:6,
from D:/Projects/searchengineproject/VokabelTrainer/game/src/GlobalHelper.h:3,
from D:\Projects\searchengineproject\vocabulary\game\src\rendering\HierarchyPanel.h:3,
from D:\Projects\searchengineproject\vocabulary\game\src\rendering\HierarchyPanel.cpp:1:
D:/Program Files/CLion 2022.3.3/bin/mingw/lib/gcc/x86_64-w64-mingw32/11.2.0/include/c++/bits/unique_ptr.h:469:19: note: declared here
469 | unique_ptr& operator=(const unique_ptr&) = delete;
| ^~~~~~~~
mingw32-make[3]: *** [game\CMakeFiles\game_lab_3.dir\build.make:316: game/CMakeFiles/game_lab_3.dir/src/rendering/HierarchyPanel.cpp.obj] Error 1
mingw32-make[3]: *** Waiting for unfinished jobs....
mingw32-make[2]: *** [CMakeFiles\Makefile2:2095: game/CMakeFiles/game_lab_3.dir/all] Error 2
mingw32-make[1]: *** [CMakeFiles\Makefile2:2102: game/CMakeFiles/game_lab_3.dir/rule] Error 2
mingw32-make: *** [Makefile:1047: game_lab_3] Error 2
我在互联网上读到过类似的问题,但解决方案都是关于避免使用复制构造函数,这应该在我的情况下定义。
我可能会错过什么?
std::unique_ptr 不能分配给另一个(右值)std::unique_ptr。这是因为当原始的 unique_ptr 删除其数据时,它的剩余副本将是一个悬空指针(不好)。
如果您想删除之前分配的数据并与新分配的数据交换,请使用重置方法。
如果您想移动所有权(本质上是更改哪个 unique_ptr 应该负责删除和包含数据),您可以使用 std::move 将一个 unique_ptr 分配给另一个 unique_ptr。
例如:
class Integer
{
public:
int data;
Integer(int _data) : data(_data)
{std::cout << “made integer ” << _data << “\n”;
~Integer(){std::cout << “destructed integer ”
<< data << “\n”;}
}
int main()
{
std::unique_ptr<Integer> iptr =
std::make_unique<Integer>(5);
std::cout << *iptr << “\n;
std::unique_ptr<Integer> new_owner =
std::move(iptr);
new_owner.reset(new Integer(10));
std::cout << *new_owner << “\n”;
}
输出
made integer 5
5
destructed integer 5
made integer 10
10