C++类设计:协方差

C++ class design: Covariance

本文关键字:方差 C++      更新时间:2023-10-16

问题

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

我的方法

算法派生自

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-types。一个例子是稀疏矩阵和三角矩阵,它们都派生自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();
};    

实际上,它是工厂方法模式的应用程序,具有以下角色:

  • 相似性算法是工厂,
  • 具体算法是混凝土工厂
  • 分数收藏是产品
  • SymetricScoreCollection是具体的产品

补充说明:

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

在以下声明中:

ScoreCollection sc = sa.runAll();

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

但是,以下语句将成功:

ScoreCollection& rsc = sa.runAll();

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

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