繁体   English   中英

在庞大的对象树中跟踪修改

[英]Tracking modifications in a huge tree of objects

我用C ++ / Qt开发了一个图形编辑器,该编辑器使用对象树作为其数据模型。 对象的类也形成一个类层次结构。 您可以想到某种GUI框架中的小部件树,例如Java Swing或Qt。 现在,我要实现撤消/重做功能。 因此,我需要跟踪对树节点(例如,更改对象属性)以及树本身(例如,添加,删除节点)的所有修改。 不幸的是,树对象也会被第三方代码修改,我必须确保该代码不会破坏我的应用程序。

因此,考虑到该树将是巨大的(数十万个节点),我如何确保可以看到对树的每次修改? 还应注意,树节点包含许多可修改的属性。

命令模式是执行此操作的一种方法。 但是,对数据的每次修改都需要通过Command对象完成,并由撤消系统记录。 从一开始就最好包括这种东西。 进行改装可能会很痛苦。

如果您无法拦截第三方代码的修改并将其转换为Commands,则可能只需在每次更改之前对所有内容进行快照。 如果您的数据结构很大,则存在明显的问题。 您可以在撤消堆栈上有一个特殊的命令,用于仅存储用于第三方修改的快照。

我没有使用/ Qt的经验,但是尽管这在标准c ++中相当复杂,但有可能。

在您真正理解我在这里所说的内容之前,请注意,在发布之前,我没有在代码中尝试此操作。 应该像一般概念一样理解它,而不是复制粘贴(其中可能有错误)

首先,您需要一个基类来表示您的节点,我们称它为Node。 该节点应为任何值提供一个变量。

class Node
{
public: // Methods
  template <typename Type>
  void Set(const char* name, GenericData& attribute) const
  {
    // Note that GenericData now is required to have an implemented copy constructor
    m_Attributes[name] = new Type(dynamic_cast<Type>(attribute));
    // Note the dynamic cast to prevent slicing

    // Call back some function to let it now the node changed here
  }

private: // Data
  // I just used a map for simplicity's sake. You should probably use
  // another container more adequate to your needs.
  std::map<std::string, GenericData*> m_Attributes;
}

然后,我们需要一般性地解决各种不同类型的问题,这也必须使用继承来完成。

class GenericData
{
public:
  virtual ~GenericData() {}
}

// Example Data
template <typename T>
class Data : public GenericData
{
public:
  ~Data(void) { delete m_Data; }
  T* get(void) const { return m_Data; }
  void set(T& dat)
  {
    delete m_Data;
    m_Data = new Data(); // Note: All data is now required to have default ctor
  }

private:
 T* m_Data;
}

然后,客户端将键入以下内容:

Data<int> MyDat = 5; // Should be optimized to copy construction, therefore work
YourTree[TheNode].Set<int>("AttributeName", MyDat);

就像我说的那样,这比实现更像是伪代码,但是应该给出一个概念。

暂无
暂无

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

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