我正在研究Qt应用程序中的表的实现,但在设计正确时遇到一些麻烦。
我有两个课程,Table
和Cell
。
Cell
具有用于设置单元格属性(如边框和填充)以及使用int Cell::row()
和int Cell::column()
获取单元格的行和列的API。它是一个显式共享类,使用QExplicitlySharedDataPointer作为其数据。它还有一个isValid()
API来查询单元格是否有效。
Table
具有用于插入/删除行和列以及合并单元格区域的API。可以使用Cell
从表中检索Table::cellAt(int row, int column)
。细胞行保持为QList<QList<Cell>>
。删除行和列时,表中将删除的单元格标记为无效,这使得对已删除的行/列中任何先前返回的单元格的Cell::isValid
的调用返回false。
现在到了棘手的部分:由于计算单元格的行数和列数(如果尚未获得它们)是一项昂贵的操作,Table::cellAt(int row, int column)
方法会在{{1}上显式设置行/列在返回之前,Cell
会将它们保持为简单的Cell
成员。这意味着int
可以在查询其行/列时快速回复。
但问题来了;这也意味着如果在单元格所在的行/列之前删除/插入行或列,则Cell
和Cell::row()
的值将不正确。
我无法将受影响的单元格标记为无效,就像删除它们所属的实际行/列时一样。由于以后有人可能会再次在该行/列中检索Cell::column
的单元格。那个细胞不应该是无效的。
有没有人对这里更好的设计有一些建议?
答案 0 :(得分:2)
你可以做一个懒惰的更新。也就是说,不是每次表更改时更新单元格的位置信息,而是在自上次更新单元格位置后表格已更改时,仅在调用Cell:row
或Cell:column
时更新它。这需要您在Table
和Cell
中保留版本标记或其他内容。每次表格更新时,都会碰撞版本。 Cell::row
和Cell:column
会首先检查Cell
的版本是否早于Table
,如果是,请重新计算该位置。
额外的工作是否值得,而不是总是重新计算位置或重新计算每一个变化,我不能说。
答案 1 :(得分:0)
我和一位朋友讨论过这个问题,因为它看起来太像编程珍珠了。这就是我们想出的:
struct Index { int n; };
。QList<Index*>
中。我们称之为Dimension
。正如您稍后将看到的,使用指针至关重要。Dimension
中每个元素的元素。当查询它们的行和列时,现在有一个额外的指针取消引用,这不应该太贵。Dimension
中添加项目或从中删除项目,并更新以下项目的n
值。存储指针是必要的,因为QList
复制了它的值。不是重新编号受表操作影响的每个Cell,而是一个成本为O(行 x 列)的操作,您现在只更新受影响的行或列,其成本为O(行 + 列)。当查询Cell的行或列时,缺点是增加了代码复杂性和两个解除引用的访问。