我对C++相当陌生,并且正在从事一个个人项目。我想在C++中创建一个C++,其中每个Entity对象都是唯一的。我想要创建的header Entity.h中有一个类。现在实体接受两个成员变量:
Rectangle rect --一个Rectangle类型的对象,它有四个浮点变量作为成员变量(x1、y1、x2、y2),它们是rectanglevector<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、赋值构造函数和析构函数吗?另外,如果我想实现将一个实体复制到另一个实体(深度复制),那么是否有必要将所有3(复制、分配和析构函数)都复制到另一个实体中?
发布于 2021-09-21 15:48:06
我这里的问题是,类实体应该是什么样子?我应该为这个类分别创建CopyConstructor、赋值构造函数和析构函数吗?另外,如果我想实现将一个实体复制到另一个实体(深度复制),那么是否有必要将所有3(复制、分配和析构函数)都复制到另一个实体中?
这个问题的答案并不取决于Entity看起来是什么样子,而是取决于它打算拥有什么样的语义。
您说每个Entity都是“唯一的”,但是C++中的每个对象(甚至每个int,即使它们恰好具有相同的值)在技术上都是唯一的。你真正的意思是什么?
Entity应该是可复制的吗?复制构造一个Entity意味着两个Entity对象具有相同的内容(如果组件指针是浅拷贝的,逻辑上是深复制的)。否则,您可能不希望编写(或可能显式delete )复制构造函数和/或副本赋值操作符.。
Entity应该是可移动的吗?可能是的,因为它不违反唯一性,并使它们更容易有效地使用。如果是这样的话,您应该确保它有一个移动构造函数和移动赋值操作符(通过编写它或安排编译器生成有用的缺省值)。
如果要实现将一个实体复制到另一个实体(深度复制),也可以使用
。
这似乎违反了您的唯一性约束,但是的,您需要一个副本构造函数和副本赋值操作符。
但是,最佳实践是避免将资源管理与程序逻辑交织在一起。因此,与其编写所有这些,不如考虑让智能指针为您自动化。有关比较,请参见this answer中提到的零规则。
实际上,我们可以用很少的代码来说明所有合理的语义:
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代码交织在一起是多么的混乱,而不是像这样被收集到一个地方。
https://stackoverflow.com/questions/69247650
复制相似问题