1

问题

我想实现一些在图表上工作的算法并返回节点对的分数,指示这些节点是否相似。这些算法应该适用于单个节点对和所有可能的节点对。在后一种情况下,应返回集合/矩阵。

我的方法

算法源自

class SimilarityAlgorithm {
public:
  Base(const Graph& G);

  virtual double run(node u, node v) = 0; // indices for nodes in the graph

  virtual ScoreCollection& runAll() = 0;
}

现在算法在内存使用方面有所不同。一些算法可能是对称的,并且 (u, v) 和 (v, u) 的分数是相同的。这需要返回不同的 ScoreCollection 类型。一个例子是一个稀疏矩阵和一个三角矩阵,它们都从ScoreCollection.

这将归结为协变返回类型:

class SpecificAlgorithm : SimilarityAlgorithm {
public:
  double run(node u, node v);

  // The specific algorithm is symmetric and thus uses a symmetric matrix to save memory
  SymmetricScoreCollection& runAll();
}

问题

  • 这种设计方法是解决这个问题的好主意吗?
  • 是否应该公开集合都作为矩阵实现的事实?
4

1 回答 1

0

您的设计似乎适合您描述的问题。

问题:

但是,您的SpecificAlgorithm: 存在一个问题,runAll()它返回的类型与基类的虚函数不同。所以它不会被调用(或者更可能的是,由于缺少虚函数,您的代码将无法编译)。

解决方案:

ScoreCollection通过创建SymmetricScoreCollection的派生类,还可以为 使用多态方法ScoreCollection

class SymetricScoreCollection: public ScoreCollection {
//define the member functions to access the values virtual
...
}; 

class SpecificAlgorithm : public SimilarityAlgorithm {
public:
  double run(node u, node v);

  // The specific algorithm is symmetric and thus uses a symmetric matrix to save memory
  ScoreCollection& runAll();
};    

实际上它是工厂方法模式的一种应用,具有以下作用:

  • 相似度算法是工厂,
  • 具体算法是具体工厂
  • ScoreCollection 是产品
  • SymmetricScoreCollection 是具体的产品

补充说明:

返回对ScoreCollectionfrom的引用会runAll()带来一些风险。假设 sa是一个特定的算法。

在以下声明中:

ScoreCollection sc = sa.runAll();

sa.runAll()返回对 a 的引用SymetricScoreCollection,但它会将引用的对象复制到 sc,使其成为 ScoreCollection。 切片发生,多态性将无法工作。

但是,以下语句将成功:

ScoreCollection& rsc = sa.runAll();

因为 rsc 是一个引用,它仍然会引用SymetricScoreCollection返回的原始对象sa.runAll(),并且一切都会按设计工作。

您会看到返回引用时很容易出现未被注意到的错误。我建议返回一个指针而不是引用。

于 2015-02-01T17:04:45.717 回答