2

我有一个二维单元格矩阵。通常只有不可见的算法适用于这些单元格。但有时我想可视化每个单元格,所以我添加了一个指向图形对象的指针

class Cell
{
   ...
   QAbstractGraphicsItem* representation_;
   ...
}

Cell 的构造函数将representation_ 设置为0。有时另一个Visualization 类会在矩阵上进行迭代,并将元素添加到Cells 中,通过颜色将每个单元格的内容可视化。

我认为这打破了 RAII 范式。你有更好的方法吗?

我可以创建另一个二维矩阵并从那里链接到原始矩阵,以便指针位于可视化端,但那时我需要两个矩阵。

4

5 回答 5

5

正如(我认为)Scott Meyers 指出的那样,RAII 的名称是错误的。

不应该叫“资源获取就是初始化”,应该叫“销毁就是资源释放”。但我们就在我们所在的地方。

如果 Cell “拥有” 指向的对象representation_,并在其析构函数中将其删除,那么这仍然是 RAII 的一种形式,就像您可以shared_ptr使用空指针初始化 a 一样,然后将其设置为其他值。我假设您正确使用它(确保对象在创建后立即保存到某个 Cell 或其他 Cell 中,在构造函数完成和将指针存储在最终将被释放的某个位置之间没有失败的可能性)。如果是这样,您正在使用 RAII 的重要部分,即使它不是一个构造函数来完成这项工作。

这可能违反了单一责任原则。您已经让 Cell 负责表示一个单元格,并且QAbstractGraphicsItem负责管理这个对象的内存。更改representation_为智能指针类型可能会简化事情,因此在 Cell 的析构函数中不需要任何特殊代码。

如果 Cell 不“拥有” 指向的对象representation_,那么它本身也不会违反 RAII,它只是没有实现它。其他东西必须对对象的所有权负责。也许其他东西使用 RAII,也许它违反了它。为了确保对象只要 Cell 需要它就一直存在,它必须以某种方式参与到 Cell 的生命周期中(例如,如果它拥有该单元,那么你可能没问题)。因此,如果不是,则很有可能它以某种方式违反了 RAII。

于 2010-11-23T16:09:09.317 回答
2

我认为您正在寻找访问者设计模式

于 2010-11-23T14:33:41.480 回答
2

我认为您根本不会破坏RAII(资源获取即初始化),只要您的 Cell 析构函数实际上删除了 QAbstractGraphicsItem 对象(它的析构函数是虚拟的,对吗?)(如果存在)。但是,您似乎担心此体系结构中图形项和单元之间的潜在耦合。

是的,将对象存储与其表示完全分开是很有吸引力的。完美的工具(正如 Ben Voigt 所指出的)是让您从类外部扩展您的类定义的工具,并使用额外的数据元素。但是 C++ 不支持这一点。您为可视化指针保留另一个矩阵的建议是我能想到的最好的,但是您必须维护第二个数据结构。如果您不想这样做,您将需要牺牲这种完美的分离以实现实用的简单性。

假设您在任何时候都只有一个可视化处于活动状态,我认为在您的单元格中保留一个指针以供可视化系统使用没有问题。您的代码按原样很好。是的,您将数据存储和表示捆绑在一起,但这是一个非常松散的链接。您的单元格仍然不依赖于与演示相关的任何内容,除了认识到该层存在并且可能想要存储一些(不透明的)单元格特定数据。

为了解决其他建议,访问者模式对于设计可视化工具很有用,但这是一个正交设计点。如果这些访问者需要为每个单元存储额外的数据怎么办?这才是真正的问题。至于用地图模拟属性扩展,它很复杂,除非您在单个矩阵上同时运行多个可视化,否则也没有必要。

于 2010-11-23T15:28:36.340 回答
1

Cell听起来您想要扩展属性,可能包含矩阵算法不需要的颜色信息。这是一种非常动态的语言方法。

对于像 C++ 这样的静态语言,通常的方法是子类化Cell. 您的算法应该在 的矩阵上工作得很好CellSubclass,尽管如果您按值顺序将元素存储在数组中,这会使事情变得有些复杂。您可以继续这样做并将您的算法模板化,或者您可以将指针存储在数组中。

但是,如果您真的想要扩展属性,您可以使用map<void*,IPropertyValue*>inside Cell,其中IPropertyValue只需提供一个虚拟析构函数,这样您就不会在释放Cell. 检索值时需要进行转换。使用某个私有静态变量的地址作为key,保证唯一性和统一性。

编辑:如果您只想/需要存储一个指针,那么您所拥有的方式将运作良好。但是使用智能指针,并swap在分配时使用。这样,一切都将是 RAII。

于 2010-11-23T14:45:59.590 回答
0

它确实破坏了 RAII-您应该使用自释放指针。

于 2010-11-23T15:31:01.170 回答