如何使用引用成员和指针向量创建 class?
How do I create a class with reference member and vector of pointers?
我是 C++ 的新手,正在从事个人项目。我想在 C++ 中创建一个 vector<Entity*> entitities
,其中每个 Entity
对象都是唯一的。我有一个 class inside header Entity.h
我想创建。现在实体有两个成员变量:
Rectangle rect
- Rectangle
类型的对象有四个浮点变量作为成员变量 (x1, y1, x2, y2),它们是矩形两个对角的坐标
vector<Component*>
- Base class 类型 Component
的许多不同组件以及一些 Derived classes。 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 ?
我的问题是,class Entity
应该是什么样子?我应该为此 class 创建单独的 CopyConstructor、Assignment Constructor 和 Destructor 吗?另外,如果我想实现将一个实体复制到另一个实体(深度复制),是否有必要拥有所有 3 个(复制、赋值和析构函数)?
My question here is, what should the class Entity look like ? Should I create separate CopyConstructor, Assignment Constructor and Destructor for this class ? Also if I want to implement copying one Entity into another (deep copying), is it necessary to have all 3 (Copy, Assignment and Destructor) ?
这个问题的答案实际上并不取决于 Entity
看起来像什么,而是取决于它打算具有的语义。
你说每个 Entity
都是“唯一的”,但 C++ 中的每个对象(甚至每个 int
,即使它们碰巧具有相同的值)在技术上都是唯一的。那你到底是什么意思?
Entity
应该是可复制的吗?复制构造一个 Entity
意味着两个 Entity
对象具有相同的内容(如果组件指针是浅复制,则字面意思是,如果是深复制,则逻辑上是相同的)。
如果不是,您可能不想编写(或者可能显式 delete
)复制构造函数 and/or 复制赋值运算符。
Entity
应该是可移动的吗?可能是的,因为它不违反唯一性并使它们更容易有效地使用。
如果是这样,您应该确保它具有移动构造函数和移动赋值运算符(通过编写它或安排编译器生成有用的默认值)。
Also if I want to implement copying one Entity into another (deep copying)
这似乎违反了您的唯一性约束,但是是的,您需要一个复制构造函数和复制赋值运算符。
但是,最佳做法是避免将资源管理与程序逻辑交织在一起。因此,与其编写所有这些,不如考虑让智能指针为您自动完成。请参阅 零规则 以进行比较 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
代码交错而不是像这样收集到一个地方会多么混乱。
主要目的只是为了启用实体的复制。这个有用吗?
#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;
}
};
我是 C++ 的新手,正在从事个人项目。我想在 C++ 中创建一个 vector<Entity*> entitities
,其中每个 Entity
对象都是唯一的。我有一个 class inside header Entity.h
我想创建。现在实体有两个成员变量:
Rectangle rect
-Rectangle
类型的对象有四个浮点变量作为成员变量 (x1, y1, x2, y2),它们是矩形两个对角的坐标vector<Component*>
- Base class 类型Component
的许多不同组件以及一些 Derived classes。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 ?
我的问题是,class Entity
应该是什么样子?我应该为此 class 创建单独的 CopyConstructor、Assignment Constructor 和 Destructor 吗?另外,如果我想实现将一个实体复制到另一个实体(深度复制),是否有必要拥有所有 3 个(复制、赋值和析构函数)?
My question here is, what should the class Entity look like ? Should I create separate CopyConstructor, Assignment Constructor and Destructor for this class ? Also if I want to implement copying one Entity into another (deep copying), is it necessary to have all 3 (Copy, Assignment and Destructor) ?
这个问题的答案实际上并不取决于 Entity
看起来像什么,而是取决于它打算具有的语义。
你说每个 Entity
都是“唯一的”,但 C++ 中的每个对象(甚至每个 int
,即使它们碰巧具有相同的值)在技术上都是唯一的。那你到底是什么意思?
Entity
应该是可复制的吗?复制构造一个Entity
意味着两个Entity
对象具有相同的内容(如果组件指针是浅复制,则字面意思是,如果是深复制,则逻辑上是相同的)。如果不是,您可能不想编写(或者可能显式
delete
)复制构造函数 and/or 复制赋值运算符。Entity
应该是可移动的吗?可能是的,因为它不违反唯一性并使它们更容易有效地使用。如果是这样,您应该确保它具有移动构造函数和移动赋值运算符(通过编写它或安排编译器生成有用的默认值)。
Also if I want to implement copying one Entity into another (deep copying)
这似乎违反了您的唯一性约束,但是是的,您需要一个复制构造函数和复制赋值运算符。
但是,最佳做法是避免将资源管理与程序逻辑交织在一起。因此,与其编写所有这些,不如考虑让智能指针为您自动完成。请参阅 零规则 以进行比较 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
代码交错而不是像这样收集到一个地方会多么混乱。
主要目的只是为了启用实体的复制。这个有用吗?
#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;
}
};