Search code examples
c++oopoverridingpure-virtual

Is it possible to overload the implementation of a pure virtual function in the child class?


I am working on a project in which I have a base class called MSTAlgorithm (Minimum Spanning Tree Algorithm). Two classes called PrimsAlgorithm and KruskalsAlgorithm publically derive from this base class. I think this is correct as these two algorithms have an 'is-a' relationship to the base class - i.e they both are MST algorithms, just with slightly different implementations. By writing methods common to both algorithms in the base class I save having to rewrite code which is common to both algorithms and I can work with a pointer to base such as std::unique_ptr<MSTAlgorithm> algorithm = std::make_unique<KruskalsAlgorithm>() or std::unique_ptr<MSTAlgorithm> algorithm = std::make_unique<PrimsALgorithm>().

I have the following method defined pure virtual on my base class (denoting that it must be implemented by any class deriving from this base class):

class MSTAlgorithm {
  public:
    virtual std::queue<Edge> findMST(Node& startingNode) = 0; 
}

I'm trying to figure out if it's possible that I can implement findMST in the derived classes with different parameters, i.e overload this function. Due to the nature of how the algorithms work, Kruskals does not require a starting node, whereas Prims does. Is it possible to 'overload' pure virtual function implementations somehow?

The code below shows my intention, but does not compile because the compiler expects no parameter to be passed for findMST on PrimsAlgorithm:

class KruskalsAlgorithm : public MSTAlgorithm {
  public:  
    std::queue<Edge> findMST();
}
class PrimsAlgorithm : public MSTAlgorithm {
  public:
    std::queue<Edge> findMST(Node& startingNode);
}

Solution

  • If you try to create an instance of KruskalsAlgorithm, you will see that you haven't overridden findMST, you have declared a different member. Because it inherits from MSTAlgorithm but doesn't provide findMST(Node&) you won't be able to create the instance.

    To be able to use it polymorphically, the parameters have to match. You will have a call site like

    std::unique_ptr<MSTAlgorithm> algorithm;
    Node node;
    algorithm->findMST(node);
    

    I.e. there will always be a node passed. The easiest thing to do is to take a Node& parameter in KruskalsAlgorithm and do nothing with it.

    I would also advise that you use the keyword override to denote member functions that you expect to be override virtual members in a base class, so that you are warned when they don't match, as you have here.

    class KruskalsAlgorithm : public MSTAlgorithm {
      public:  
        std::queue<Edge> findMST(Node&) override;// Unnamed parameter because unused
    }