如何复制耦合课程

时间:2014-11-30 12:12:42

标签: c++

我希望有一些通用变量,我可以轻松地从XML文件写入/加载,并可能在菜单系统中使用。持有这些变量的类看起来像

class Entity
{
private:
 VarGroup group;

 Var<float> myfloat;
 Var<int> myint;

public:
 Entity() : group("group name"), myfloat("name", &group), myint("name2", &group) {}
};

Var配备了重载运算符,因此我可以像常规变量一样使用它们。它们被赋予文字名称,并且它们的基类指针被插入到组中。然后,VarGroup用于对Var类型执行批量操作,例如导入到XML或从XML导入。

问题是如果Entity对象按值存储在std::vector中,则数据可能会在内存中移动,而Var对象中的VarGroup指针将变为无效。

尝试通过VarVarGroup内的功能处理此类副本是否可能或甚至是否合理?

更多详情:

class VarBase
{
protected:
 std::string name;

public:
 VarBase(const std::string &_name) : name(_name) {}
 virtual bool toXMLNode(rapidxml::xml_document<> *doc, rapidxml::xml_node<> *parent) const = 0;
 virtual bool fromXMLNode(rapidxml::xml_node<> *node) = 0;
 std::string getName() const;
};

class VarGroup
{
private:
 std::string name;
 std::vector<VarBase*> vars;

public:
 VarGroup(const std::string &_name) : name(_name) {}

 void insert(VarBase *var)
 {
  vars.push_back(var);
 }

 bool toXMLNode(const std::string &nodeName, rapidxml::xml_document<> *doc) const;
 bool fromXMLNode(rapidxml::xml_node<> *node);
};

template<typename T>
class Var : public VarBase
{
private:
 T value;

public:
 Var(const std::string &_name, VarGroup *group) : VarBase(_name)
 {
  group->insert(this);
 }

 bool toXMLNode(rapidxml::xml_document<> *doc, rapidxml::xml_node<> *parent) const override;
 bool fromXMLNode(rapidxml::xml_node<> *node) override;

 // Implementations of operators (), =, etc.
};

1 个答案:

答案 0 :(得分:0)

我试着想办法,但这可能很危险。

我将VarGroup指针添加到Var类,以使两者以两种方式耦合。然后我添加了复制构造函数,试图在任一类的副本下保留正确的耦合,这必须是与顺序无关的。

class VarBase
{
protected:
 std::string name;

public:
 VarBase(const std::string &_name) : name(_name) {}
 virtual bool toXMLNode(rapidxml::xml_document<> *doc, rapidxml::xml_node<> *parent) const = 0;
 virtual bool fromXMLNode(rapidxml::xml_node<> *node) = 0;
 std::string getName() const;
};

class VarGroup
{
private:
 std::string name;
 std::vector<VarBase*> vars;

public:
 VarGroup(const std::string &_name) : name(_name) {}

 VarGroup(const VarGroup &that)
 {
  name = that.name;
  vars = that.vars;

  for(auto base : vars)
   base->pGroup = this;
 }

 // Swap existing VarBase pointer with new one.
 void swap(VarBase *newVar, VarBase *oldVar)
 {
  auto it = find(vars.begin(), vars.end(), oldVar);
  *it = newVar;
 }

 void insert(VarBase *var)
 {
  vars.push_back(var);
 }

 bool toXMLNode(const std::string &nodeName, rapidxml::xml_document<> *doc) const;
 bool fromXMLNode(rapidxml::xml_node<> *node);
};

template<typename T>
class Var : public VarBase
{
friend class VarGroup;
private:
 T value;
 VarGroup *pGroup;

public:
 Var(const std::string &_name, VarGroup *_pGroup) : VarBase(_name), pGroup(_pGroup)
 {
  pGroup->insert(this);
 }

 Var(const Var &that)
 {
  pGroup = that.pGroup;
  value = that.value;

  pGroup->swap(this, &that);
 }

 bool toXMLNode(rapidxml::xml_document<> *doc, rapidxml::xml_node<> *parent) const override;
 bool fromXMLNode(rapidxml::xml_node<> *node) override;

 // Implementations of operators (), =, etc.
};

现在,有两个副本案例:

1)首先复制VarGroup个对象。

它访问“待复制”Var对象以将其组指针更改为新对象。 复制Var个对象后,它们会复制旧VarGroup对象中的新Var地址。然后通过该新指针,他们调用新的VarGroup对象将其旧Var对象地址更改为新对象。

2)首先复制Var个对象。

复制构造函数复制旧组地址(冗余操作)。然后它交换“待复制组”中的Var地址。复制VarGroup对象时,它已经具有新的Var地址(如果已复制所有Var个对象)。然后,它访问新的Var对象,将其组指针更改为新的。

这听起来过于复杂,但可能会起作用吗?