简体   繁体   English

复制链接在一起的类

[英]copying classes linked together

I have few different types of classes which are cross linked (they contain pointers to each other - some of them vectors of pointers) and I am pretty happy with this design. 我有几种不同类型的交叉链接的类(它们包含彼此的指针-其中一些是指针向量),对此设计我感到非常满意。 But now it come a point where I would like to make a copy of all my structure and its very hard to correct all the links of every instance of the new classes. 但是现在到了要复制所有结构的地步,而且很难纠正新类每个实例的所有链接。 I already have a container class for all the structure but still the attempts I made to write a clone() method ended up in very dirty code and I am not satisfied with them. 我已经为所有结构提供了一个容器类,但是仍然尝试写一个clone()方法以很脏的代码结束,我对它们不满意。

I would like to know if there is a kind of design pattern that could help to solve this problem. 我想知道是否存在一种可以帮助解决此问题的设计模式。

One solution that might help you (if I understood correctly from your rather vague description): 一种可能对您有帮助的解决方案(如果我从您的模糊描述中正确理解的话):

  1. create a clone of all your objects (by now, just copy all pointers to the new objects still pointing to the original objects) 创建所有对象的克隆(到现在为止,只需将所有指针复制到仍然指向原始对象的新对象)
  2. while doing so, keep track of which object is the clone of which object in some sort of dictionary (something like std::map<void*,void*> should do the job, but maybe you can come up with something better than the ugly void* ) 在执行此操作时,请跟踪某个字典中哪个对象的克隆(例如std::map<void*,void*>应该可以完成此工作,但也许您可以提出比该对象更好的东西)丑陋的void*
  3. go through all the new objects and redirect all pointers by the values stored in the dictionary 遍历所有新对象并通过存储在字典中的值重定向所有指针

The usual approach is to keep some sort of a mapping form old to new pointers - before making a copy, consult the map to see if the object was already copied and if it is, return the existing copy, otherwise, call clone(). 通常的方法是保留某种旧到新指针的映射形式-在进行复制之前,请查阅地图以查看对象是否已被复制,如果是,则返回现有副本,否则,调用clone()。

Something like this: 像这样:

#include <unordered_map>
#include <vector>

typedef std::unordered_map<void *, void *> map_type;

template<typename T>
T *clone (T *ptr, map_type &m)
{
  auto p = m.find (ptr);
  if (p != m.end ())
    return static_cast<T *> (p->second);
  else
    return ptr->clone (m);
}

struct S
{
  int x;
  std::vector<S *> v;

  S *clone (map_type &m)
  {
    S *p = new S;

    // this is important to happen before calling clone() on subobjects
    m [this] = p;

    p->x = x;   
    for (auto q: v)
      p->v.push_back (::clone (q, m));

    return p;
  }
};

int
main ()
{
  S *p = new S ();
  p->x = 1;

  S *q = new S ();
  q->x = 2;

  S *r = new S ();
  r->x = 3;

  p->v.push_back (p);
  p->v.push_back (p);
  p->v.push_back (q);

  q->v.push_back (p);
  q->v.push_back (r);

  r->v.push_back (p);

  map_type m;

  S *x;
  x = clone (p, m);
}

It might be a bit cleaner if you can impose hierarchy (child-parent relationship) together with the links. 如果可以将层次结构(子级-父级关系)与链接一起强加,可能会更干净一些。 Then you may approach cloning process recursively - let each of the parents clone all of all its children while being cloned and updating references. 然后,您可以递归地进行克隆过程-让每个父母在克隆和更新引用时都克隆其所有子级。

In case you have relationship on the same level (say, objects being peers and cross-referencing each other in circle), you can artificially add parent that would clone all children, update its own references, and then update children with new references. 如果您在同一级别上有关系(例如,对象是同级对象,并且彼此交叉引用),则可以人为地添加父级,它将克隆所有子级,更新其自己的引用,然后使用新的引用更新子级。

This would allow scaling/adding new components without modifying much of the code. 这将允许缩放/添加新组件而无需修改大量代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM