e.doroskevic
e.doroskevic

Reputation: 2167

Why do I need to re-declare `virtual` methods in my Sub-Class? [C++ / Polymorphism]

Can somebody explain, if we have an abstract class with a virtual member function, why do we need to declare it again in our sub-class? For instance, see example below

Abstract Class

.h file

#ifndef ALGORITHM_H
#define ALGORITHM_H

#include <vector>
#include "Event.h"

using std::vector;

class Algorithm{
protected:
  vector<Event>* dataset;
public:
  Algorithm(vector<Event>& dataset);
  virtual ~Algorithm();

  virtual void run() = 0;
};

#endif

.cpp file

#include "../include/Algorithm.h"

Algorithm::Algorithm(vector<Event>& dataset):dataset(&dataset){}
Algorithm::~Algorithm(){}

Given the pure virtual function run is declared, by extending this class, my expectation was it will only require implementation. However, it still requires declaration in class that extends this abstract-class.

Sub-Class

.h file

#ifndef SELECT_ALGORITHM_RANDOM_H
#define SELECT_ALGORITHM_RANDOM_H

#include "Algorithm.h"

class SelectAlgorithmRandom : public Algorithm{
public:
  SelectAlgorithmRandom(vector<Event>& dataset);
  ~SelectAlgorithmRandom();

  void run(); // <-- why do I need this here, and doesn't it defy the purpose of me declaring virtual `run` function in `Algorithm`? 
};

#endif

.cpp file

#include "../include/SelectAlgorithmRandom.h"

SelectAlgorithmRandom::SelectAlgorithmRandom(vector<Event>& dataset):Algorithm(dataset){}
SelectAlgorithmRandom::~SelectAlgorithmRandom(){}

void SelectAlgorithmRandom::run(){
  //  TODO
}

Upvotes: 1

Views: 457

Answers (3)

Bo Persson
Bo Persson

Reputation: 92271

You have to declare the run() function in the declaration of SelectAlgorithmRandom to show that you actually intend to define it for that class.

If not, SelectAlgorithmRandom would also be an abstract class and the function could be defined in a further derived class. Perhaps several levels down.

Upvotes: 1

Raindrop7
Raindrop7

Reputation: 3911

In short if you want to achieve polymorphism use virtual methods and pointers to base classes.

class A{
    public:
        virtual void F(){std::cout << "Base A::Foo()" << std::endl;}
};

class B : public A{
    public:
       void F(){std::cout << "B::Foo()" << std::endl;}
};

Now in main:

int main(){

    A* ptrA = new B;
    ptrA->Foo();

    return 0;
}

As you can see above the method Foo is invoked depending on the object type that ptrA points to.

  • Method overriding requires re-declaring virtual methods in derived classes.

Upvotes: 1

You have to add the declaration, because the C++ standard demands that each and every member of a class be declared in the class definition itself:

[class.mem]/1:

The member-specification in a class definition declares the full set of members of the class; no member can be added elsewhere.

Members refers to both functions and data. The fact there is a pure virtual function in Algorithm doesn't automatically mean that SelectAlgorithmRandom is also going to define it. Classes can be kept abstract through several layers of an inheritance hierarchy.

To define the run function, you must specify that intent explicitly in the class definition.

And by the way, in modern C++, it's best to declare the function is meant as an override:

void run() override;

That way the compiler checks it against the definition of the base class version, to ensure you are really overriding something in the base, and not adding an overload or some unrelated function.

Upvotes: 7

Related Questions