我如何创建一个类与引用成员和指针向量?



我对c++相当陌生,正在做一个个人项目。我想在c++中创建一个vector<Entity*> entitities,其中每个Entity对象都是唯一的。我有一个类里面的头Entity.h,我想创建。现在Entity接受两个成员变量:

  1. Rectangle rect-一个Rectangle类型的对象,它有四个float变量作为成员变量(x1, y1, x2, y2),它们是矩形的两个相对角的坐标
  2. vector<Component*>-一些不同的组件的基类类型Component与一些派生类。Class Component的代码如下所示:
/*************************** BASE CLASS **************************/
class Component
{
public:
virtual ~Component() = default;
virtual Component* Clone() = 0;
};
/*************************** DERIVED CLASS 1 **************************/
class BasicComponent: public Component
{
private:
int B= 0;
public:
BasicComponent* Clone() override {
return new BasicComponent(B);
}
BasicComponent(const int& mB) :B(mB){}
BasicComponent() :B(0) {}
};
/*************************** DERIVED CLASS 2 **************************/
class AdvancedComponent: public Component
{
private:
float A = 0.f;
int iA = 0;
public:
AdvancedComponent* Clone() override {
return new AdvancedComponent(A, iA);
}
AdvancedComponent(const float& mA, const int& miA) :A(mA),iA(miA) {}
AdvancedComponent() :A(0.f),iA(0) {}
};

因为我想要每个Entity在矢量实体是唯一的,也就是说,有它自己的矩形和组件,我应该如何创建类?

我的问题是,class Entity应该是什么样子?我应该为这个类创建单独的CopyConstructor, assign Constructor和Destructor吗?另外,如果我想实现将一个实体复制到另一个实体(深度复制),是否有必要拥有所有3(复制,赋值和析构)?

我的问题是,类实体应该是什么样子?我应该为这个类创建单独的CopyConstructor, assign Constructor和Destructor吗?另外,如果我想实现将一个实体复制到另一个实体(深度复制),是否有必要拥有所有3(复制,赋值和析构)?

这个问题的答案并不取决于Entity看起来像什么,而是取决于它打算具有什么样的语义。

你说每个Entity都是"唯一的",但是c++中的每个对象(甚至每个int,即使它们碰巧具有相同的值)在技术上都是唯一的。你到底是什么意思?

  1. Entity应该是可复制的吗?复制构造一个Entity意味着两个Entity对象具有相同的内容(字面上,如果组件指针是浅复制的,逻辑上,如果它们是深复制的)。

    如果没有,您可能不想编写(或者可能显式地deletethe)复制构造函数和/或复制赋值操作符。

  2. Entity应该是可移动的吗?可能是的,因为它不违反唯一性,并且使它们更容易有效地使用。

    如果是,您应该确保它具有move构造函数和move赋值操作符(通过编写或安排编译器生成有用的默认值)。

如果我想实现将一个实体复制到另一个实体(深度复制)

这似乎违反了惟一性约束,但是,是的,您需要为此提供复制构造函数和复制赋值操作符。

然而,最佳实践是避免将资源管理与程序逻辑交织在一起。所以,与其写这些,不如考虑让一个智能指针帮你自动完成。请参阅本回答中提到的零规则的比较。

实际上,我们可以用很少的代码说明所有合理的语义:

template <typename ComponentPtr>
struct ZeroEntity
{
Rectangle bound;
std::vector<ComponentPtr> components;
};
using ShallowCopyZeroEntity = ZeroEntity<std::shared_ptr<Component>>;
using NoCopyOnlyMoveEntity = ZeroEntity<std::unique_ptr<Component>>;
using DeepCopyZeroEntity = ZeroEntity<my::clone_ptr<Component>>;

除了我们仍然需要写一个深度复制的clone_ptr,就像

namespace my {
template <typename T>
class clone_ptr
{
std::unique_ptr<T> p_;
std::unique_ptr<T> clone() const { return std::unique_ptr<T>{p_ ? p_->Clone() : nullptr}; }
public:
using pointer = typename std::unique_ptr<T>::pointer;
explicit clone_ptr(pointer p) : p_(p) {}
// copy behaviour is where the cloning happens
clone_ptr(clone_ptr const& other) : p_(other.clone()) {}
clone_ptr& operator=(clone_ptr other)
{
other.swap(*this);
}
// move behaviour (and destructor) generated by unique_ptr
clone_ptr(clone_ptr&& other) = default;
clone_ptr& operator=(clone_ptr&&) = default;
// now write all the same swap, release, reset, operator* etc. as std::unique_ptr
};
}

…如果这看起来很多,想象一下它与你的Entity代码交错在一起会有多混乱,而不是像这样收集到一个地方。

主要目的只是为了复制实体。这个可以吗?

#include "Components.h"
#include "Rectangle.h"
#include <vector>
using namespace std;
class Entity
{
public:
Rectangle& Box;
vector<Component*>& Components;
//Default constructor call
Entity(): Box(*new Rectangle), Components(*new vector<Component*>){}

//Constructor call with parameters
Entity(Rectangle& B, vector<Component*>& C) : Box(B), Components(C){}
//Copy constructor that makes Entity copyable
Entity(const Entity& E) : Box(*new Rectangle(E.Box)), Components(*new vector<Component*>(E.Components.size())) {


for (unsigned int i = 0; i < E.Components.size(); i++) {
Components[i] = E.Components[i]->Clone();
}
}
//Assignment operator constructor
Entity& operator=(const Entity& E){ 
//Entity* pE = &E;
if (this != &E)
{
delete& Box;
delete& Components;
Box = *new Rectangle(E.Box);
Components = *new vector<Component*>(E.Components.size());
for (unsigned int i = 0; i < E.Components.size(); i++) {
Components[i] = E.Components[i]->Clone();
}
}
return *this;
}
};

最新更新