首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何创建具有引用成员和指针向量的类?

如何创建具有引用成员和指针向量的类?
EN

Stack Overflow用户
提问于 2021-09-19 22:56:02
回答 2查看 128关注 0票数 1

我对C++相当陌生,并且正在从事一个个人项目。我想在C++中创建一个C++,其中每个Entity对象都是唯一的。我想要创建的header Entity.h中有一个类。现在实体接受两个成员变量:

  1. Rectangle rect --一个Rectangle类型的对象,它有四个浮点变量作为成员变量(x1、y1、x2、y2),它们是rectangle
  2. vector<Component*>的两个相对角的坐标--基类类型Component的许多不同组件具有一些派生类。Class Component的代码如下所示:

代码语言:javascript
运行
复制
/*************************** 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(复制、分配和析构函数)都复制到另一个实体中?

EN

Stack Overflow用户

回答已采纳

发布于 2021-09-21 15:48:06

我这里的问题是,类实体应该是什么样子?我应该为这个类分别创建CopyConstructor、赋值构造函数和析构函数吗?另外,如果我想实现将一个实体复制到另一个实体(深度复制),那么是否有必要将所有3(复制、分配和析构函数)都复制到另一个实体中?

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

您说每个Entity都是“唯一的”,但是C++中的每个对象(甚至每个int,即使它们恰好具有相同的值)在技术上都是唯一的。你真正的意思是什么?

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

否则,您可能不希望编写(或可能显式delete )复制构造函数和/或副本赋值操作符.。

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

如果是这样的话,您应该确保它有一个移动构造函数和移动赋值操作符(通过编写它或安排编译器生成有用的缺省值)。

如果要实现将一个实体复制到另一个实体(深度复制),也可以使用

这似乎违反了您的唯一性约束,但是的,您需要一个副本构造函数和副本赋值操作符。

但是,最佳实践是避免将资源管理与程序逻辑交织在一起。因此,与其编写所有这些,不如考虑让智能指针为您自动化。有关比较,请参见this answer中提到的零规则。

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

代码语言:javascript
运行
复制
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之外,类似于

代码语言:javascript
运行
复制
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代码交织在一起是多么的混乱,而不是像这样被收集到一个地方。

票数 2
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69247650

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档