我正在开发一个项目,其中有一个名为
MSTAlgorithm
(最小生成树算法)的基类。称为 PrimsAlgorithm
和 KruskalsAlgorithm
的两个类公开派生自该基类。我认为这是正确的,因为这两种算法与基类具有“is-a”关系 - 即它们都是 MST 算法,只是实现略有不同。通过在基类中编写两种算法通用的方法,我不必重写两种算法通用的代码,并且我可以使用指向基类的指针,例如 std::unique_ptr<MSTAlgorithm> algorithm = std::make_unique<KruskalsAlgorithm>()
或 std::unique_ptr<MSTAlgorithm> algorithm = std::make_unique<PrimsALgorithm>()
。我在我的基类上定义了以下纯虚拟方法(表示它必须由从此基类派生的任何类实现):
class MSTAlgorithm {
public:
virtual std::queue<Edge> findMST(Node& startingNode) = 0;
}
我试图弄清楚是否可以在具有不同参数的派生类中实现
findMST
,即重载此函数。由于算法工作方式的本质,Kruskals 不需要起始节点,而 Prims 则需要。是否有可能以某种方式“重载”纯虚函数实现?
下面的代码显示了我的意图,但无法编译,因为编译器不希望在findMST
上为
PrimsAlgorithm
传递任何参数:class KruskalsAlgorithm : public MSTAlgorithm {
public:
std::queue<Edge> findMST();
}
class PrimsAlgorithm : public MSTAlgorithm {
public:
std::queue<Edge> findMST(Node& startingNode);
}
KruskalsAlgorithm
的实例,您将看到您没有覆盖
findMST
,您已经声明了另一个成员。因为它继承自 MSTAlgorithm
但不提供 findMST(Node&)
,因此您将无法创建实例。为了能够多态地使用它,参数必须匹配。您将有一个类似的呼叫站点
std::unique_ptr<MSTAlgorithm> algorithm;
Node node;
algorithm->findMST(node);
即总会有一个节点通过。最简单的方法是在
Node&
中获取
KruskalsAlgorithm
参数,并且不对其执行任何操作。我还建议您使用关键字 override
来表示您希望覆盖基类中的虚拟成员的成员函数,这样当它们不匹配时您就会收到警告,就像这里一样。
class KruskalsAlgorithm : public MSTAlgorithm {
public:
std::queue<Edge> findMST(Node&) override;// Unnamed parameter because unused
}
如果无法更新父类,则可以解决新子类中出现额外意外参数的问题:创建一个额外的方法来接收并记住额外的参数。在调用站点,分两个阶段完成工作 - 传递新参数,然后调用常规重写方法。
您甚至可以创建一个执行这两种操作的非虚拟方法,并为其指定与虚拟方法相同的名称,但这不会使其以多态方式运行。