C++ "Virtual" Keyword For Functions in Derived Classes. Is It Necessary

C++ virtual keyword for functions in derived classes. Is it necessary?

They are exactly the same. There is no difference between them other than that the first approach requires more typing and is potentially clearer.

Do ALL virtual functions need to be implemented in derived classes?

Derived classes do not have to implement all virtual functions themselves. They only need to implement the pure ones.1 That means the Derived class in the question is correct. It inherits the bar implementation from its ancestor class, Abstract. (This assumes that Abstract::bar is implemented somewhere. The code in the question declares the method, but doesn't define it. You can define it inline as Trenki's answer shows, or you can define it separately.)


1 And even then, only if the derived class is going to be instantiated. If a derived class is not instantiated directly, but only exists as a base class of more derived classes, then it's those classes that are responsible for having all their pure virtual methods implemented. The "middle" class in the hierarchy is allowed to leave some pure virtual methods unimplemented, just like the base class. If the "middle" class does implement a pure virtual method, then its descendants will inherit that implementation, so they don't have to re-implement it themselves.

Should I use virtual, override, or both keywords?

When you override a function you don't technically need to write either virtual or override.

The original base class declaration needs the keyword virtual to mark it as virtual.

In the derived class the function is virtual by way of having the ¹same type as the base class function.

However, an override can help avoid bugs by producing a compilation error when the intended override isn't technically an override. For instance, the function type isn't exactly like the base class function. Or that a maintenance of the base class changes that function's type, e.g. adding a defaulted argument.

In the same way, a virtual keyword in the derived class can make such a bug more subtle by ensuring that the function is still virtual in the further derived classes.

So the general advice is,

  • Use virtual for the base class function declaration.

    This is technically necessary.

  • Use override (only) for a derived class' override.

    This helps maintenance.

Example:

struct Base { virtual void foo() {} };
struct Derived: Base { void foo() override {} };


Notes:

¹ C++ supports covariant raw pointer and raw reference results. With covariance the type of the override isn't exactly the same. It just has a compatible type.

Why do we need virtual functions in C++?

Without "virtual" you get "early binding". Which implementation of the method is used gets decided at compile time based on the type of the pointer that you call through.

With "virtual" you get "late binding". Which implementation of the method is used gets decided at run time based on the type of the pointed-to object - what it was originally constructed as. This is not necessarily what you'd think based on the type of the pointer that points to that object.

class Base
{
public:
void Method1 () { std::cout << "Base::Method1" << std::endl; }
virtual void Method2 () { std::cout << "Base::Method2" << std::endl; }
};

class Derived : public Base
{
public:
void Method1 () { std::cout << "Derived::Method1" << std::endl; }
void Method2 () { std::cout << "Derived::Method2" << std::endl; }
};

Base* basePtr = new Derived ();
// Note - constructed as Derived, but pointer stored as Base*

basePtr->Method1 (); // Prints "Base::Method1"
basePtr->Method2 (); // Prints "Derived::Method2"

EDIT - see this question.

Also - this tutorial covers early and late binding in C++.

Why are virtual functions preferable over derived class objects?

The huge benefit that you get for using the base class pointer type and virtual functions is that you can have one single list that contains several different types of Shape and you can process them all in a single function where they will all have different behaviors due to their derived types.

As an example, I modified your code by adding the function DrawAllShapes that takes in a vector<Shapes*>&. (Be careful of using raw pointers. You really should use vector<std::unique_ptr<Shape>>&here or something like that.

You have incredible flexibility with this pattern that lets you call the same function on a collection of base class pointer objects but results in different behavior for every object in the collection depending on its derived type.

#include <iostream>
#include <vector>
using namespace std;

//////////////////////////////////////////////////////
//base class
class Shape {

public:
virtual void draw() = 0; //pure virtual function
};

//derived classes
class Square : public Shape {

public:
void draw() {
cout << "Draw square" << endl;
}

};

class Circle : public Shape {

public:
void draw() {
cout << "Draw circle " << endl;
}

};

void DrawAllShapes(std::vector<Shape*>& shapes) {
for (int i = 0; i < shapes.size(); ++i) {
shapes[i]->draw();
}
}

//////////////////////////////////////////////////////
int main()
{
std::vector<Shape*> shapeVec{ new Square, new Circle, new Square, new Square, new Circle };
DrawAllShapes(shapeVec);

system("pause");
}

Also, imagine if you were using a prebuilt graphical library that already had a Shape class and several shapes defined. What if you wanted to add your own new type of Shape and have it work perfectly with all of the library's functions? All you would have to do is create your own derived class and implement all of the necessary virtual functions exposed by the library's Shape class and then you've literally extended the library beyond its original capabilities.

Using 'virtual' in derived class

virtual is needed for overrideable functions at the highest (least derived) level. It is optional, but harmless at lower (more derived) levels. It's good for self-documenting the code.

C++ override specifier without virtual? Does override imply virtual?

The answer you're looking for is in https://en.cppreference.com/w/cpp/language/virtual

If some member function vf is declared as virtual in a class Base, and some class Derived, which is derived, directly or indirectly, from Base, has a declaration for member function with the same
name
parameter type list (but not the return type)
cv-qualifiers
ref-qualifiers
Then this function in the class Derived is also virtual (whether or not the keyword virtual is used in its declaration) and overrides Base::vf (whether or not the word override is used in its declaration).

Why must I re-declare a virtual function from an inherited class?

It doesn't work this way. You need to declare the methods you're going to define, whether they're overriding a virtual method or not.

This isn't just an unreasonable requirement of the language. Without this you would be unable to define partially virtual class, i.e., you could have BaseSubtype that has common implementation of method1() but requires classes derived from it to implement method2() and method3()

When is the virtual attribute actually needed in a derived class?

For what I've tried, having virtual on a function in the base class automatically makes that function virtual for any descendants.

This is true, the child automatically inherits the virtualness of the parent method.

People restate virtual in child classes as a convention simply to explicitly show that the child intends to override a virtual method (we have override in C++11 though).



Related Topics



Leave a reply



Submit