2

I am currently working through the Educative course Grokking the Coding Interview. While it is a very good course and does explain the algorithms very well, it does not always explain the code.

A few times I have seen the use of virtual functions, as a dynamic function (to be clear, I mean functions that require the instantiation of an object in order to be called). From reading up on virtual functions, I gather that they are used to achieve some OOP principles such as run time polymorphism, or just generally improving the maintainability of some code. In the case of these algorithms questions, that seems to be completely unnecessary. In fact, I am able to just delete the virtual keyword and the code runs all the same.

My question is: Why might the author be using virtual to define these functions?

Here is an example of the course's author's use of virtual functions:

using namespace std;

#include <iostream>
#include <queue>
#include <vector>

class MedianOfAStream {
 public:
  priority_queue<int> maxHeap;                             // containing first half of numbers
  priority_queue<int, vector<int>, greater<int>> minHeap;  // containing second half of numbers

  virtual void insertNum(int num) {
    if (maxHeap.empty() || maxHeap.top() >= num) {
      maxHeap.push(num);
    } else {
      minHeap.push(num);
    }

    // either both the heaps will have equal number of elements or max-heap will have one
    // more element than the min-heap
    if (maxHeap.size() > minHeap.size() + 1) {
      minHeap.push(maxHeap.top());
      maxHeap.pop();
    } else if (maxHeap.size() < minHeap.size()) {
      maxHeap.push(minHeap.top());
      minHeap.pop();
    }
  }

  virtual double findMedian() {
    if (maxHeap.size() == minHeap.size()) {
      // we have even number of elements, take the average of middle two elements
      return maxHeap.top() / 2.0 + minHeap.top() / 2.0;
    }
    // because max-heap will have one more element than the min-heap
    return maxHeap.top();
  }
};

int main(int argc, char *argv[]) {
  MedianOfAStream medianOfAStream;
  medianOfAStream.insertNum(3);
  medianOfAStream.insertNum(1);
  cout << "The median is: " << medianOfAStream.findMedian() << endl;
  medianOfAStream.insertNum(5);
  cout << "The median is: " << medianOfAStream.findMedian() << endl;
  medianOfAStream.insertNum(4);
  cout << "The median is: " << medianOfAStream.findMedian() << endl;
}

Again, from everything I've read, I really just don't see the point. And, running this exact code without the virtual keyword works just fine. My thinking would be that this is some sort of best practice in C++ land.

Thanks for any explanation!

Asteroids With Wings
  • 17,071
  • 2
  • 21
  • 35
  • 3
    *"My thinking would be that this is some sort of best practice in C++ land"* - That's one option. Another is that you witness an example of cargo cult programming. So, good on you for asking. If you have a greater interest to learn idiomatic C++, consider checking out [the curated book list](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). – StoryTeller - Unslander Monica Dec 08 '20 at 22:34
  • 2
    You have a good point. In particular, `virtual` becomes useful (only) when you use inheritance. And inheriting from the class you've shown above would be a poor idea (a base class should nearly always have a virtual destructor). – Jerry Coffin Dec 08 '20 at 22:35
  • 1
    In well written code, such a `virtual` is generally understood to mean that it's a *customization point*. I.e. It's a function that is intentionally meant to be potentially overwritten by someone writing a subclass. –  Dec 08 '20 at 22:36
  • 1
    `virtual` is clearly linked to inheritance, either existing, or expected (i.e. if users might customize these classes in the future, even if there is only a base class now). You can combine this with either pure virtual (`= 0`) or certain keywords such as `final` to force/show a certain usage of the class as a whole. If nobody is going to inherit from the class however (because it's e.g. hidden in your code), I don't see any reason to use `virtual`. – Cedric Dec 08 '20 at 22:44
  • @Frank _Every_ non-`private` member function should be inheritable in that sense, or your design is not OO-friendly. `virtual` doesn't really add to (or take away from) that. – Asteroids With Wings Dec 08 '20 at 23:03

1 Answers1

2

From reading up on virtual functions, I gather that they are used to achieve some OOP principles such as run time polymorphism

Yes.

or just generally improving the maintainability of some code

No.

In the case of these algorithms questions, that seems to be completely unnecessary. In fact, I am able to just delete the virtual keyword and the code runs all the same.

Yes.

My question is: Why might the author be using virtual to define these functions?

I see three possibilities here:

  1. The author will inherit this class in a later chapter, and has "got ready" by putting virtual on the member function declarations now. I think that's a bit of an odd choice, personally (particularly as they would also likely want to add a virtual destructor at that time), but maybe keep reading and find out!

  2. The author does it, always, out of habit, even when they don't need to. Some people like to make every function virtual so that you get dynamic polymorphism "by default", without having to change your base class when you later derive from it. I think that's also a very strange thing to do, personally.

  3. The author made a mistake.

a dynamic function (to be clear, I mean functions that require the instantiation of an object in order to be called)

We call those non-static member functions.

Asteroids With Wings
  • 17,071
  • 2
  • 21
  • 35