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

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();
}

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

最佳答案

你的设计似乎适合你所描述的问题。
问题:
但是,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();
};

实际上,它是factory method pattern的一个应用程序,具有以下角色:
相似算法就是工厂,
具体算法是混凝土厂
ScoreCollection是产品
SymetricCoreCollection是具体产品
附加说明:
ScoreCollection返回对runAll()的引用会带来一些风险。假设sa是一个特定的算法。
在以下声明中:
ScoreCollection sc = sa.runAll();

sa.runAll()返回对aSymetricScoreCollection的引用,但它会将引用的对象复制到sc,使其成为scorecollection。Slicing发生,多态性将无法工作。
但以下声明将获得成功:
ScoreCollection& rsc = sa.runAll();

因为rsc是一个引用,它仍然引用由SymetricScoreCollection返回的原始sa.runAll()对象,并且一切都将按设计工作。
你看,在返回引用时,很容易出现未注意到的错误。我建议返回一个指针而不是引用。

10-04 22:23