Overriding VS Virtual

Overriding vs Virtual

This is the classic question of how polymorphism works I think. The main idea is that you want to abstract the specific type for each object. In other words: You want to be able to call the Child instances without knowing it's a child!

Here is an example:
Assuming you have class "Child" and class "Child2" and "Child3" you want to be able to refer to them through their base class (Parent).

Parent* parents[3];
parents[0] = new Child();
parents[1] = new Child2();
parents[2] = new Child3();

for (int i=0; i<3; ++i)
parents[i]->say();

As you can imagine, this is very powerful. It lets you extend the Parent as many times as you want and functions that take a Parent pointer will still work. For this to work as others mention you need to declare the method as virtual.

The difference between virtual, override, new and sealed override

The virtual keyword is used to modify a method, property, indexer or event declaration, and allow it to be overridden in a derived class. For example, this method can be overridden by any class that inherits it:
Use the new modifier to explicitly hide a member inherited from a base class. To hide an inherited member, declare it in the derived class using the same name, and modify it with the new modifier.

This is all to do with polymorphism. When a virtual method is called on a reference, the actual type of the object that the reference refers to is used to decide which method implementation to use. When a method of a base class is overridden in a derived class, the version in the derived class is used, even if the calling code didn't "know" that the object was an instance of the derived class. For instance:

public class Base
{
public virtual void SomeMethod()
{
}
}

public class Derived : Base
{
public override void SomeMethod()
{
}
}

...

Base d = new Derived();
d.SomeMethod();

will end up calling Derived.SomeMethod if that overrides Base.SomeMethod.

Now, if you use the new keyword instead of override, the method in the derived class doesn't override the method in the base class, it merely hides it. In that case, code like this:

public class Base
{
public virtual void SomeOtherMethod()
{
}
}

public class Derived : Base
{
public new void SomeOtherMethod()
{
}
}

...

Base b = new Derived();
Derived d = new Derived();
b.SomeOtherMethod();
d.SomeOtherMethod();

Will first call Base.SomeOtherMethod , then Derived.SomeOtherMethod . They're effectively two entirely separate methods which happen to have the same name, rather than the derived method overriding the base method.

If you don't specify either new or overrides, the resulting output is the same as if you specified new, but you'll also get a compiler warning (as you may not be aware that you're hiding a method in the base class method, or indeed you may have wanted to override it, and merely forgot to include the keyword).

An overriding property declaration may include the sealed modifier. Use of this modifier prevents a derived class from further overriding the property. The accessors of a sealed property are also sealed.

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.

c++ virtual keyword vs overriding function

Consider the following example. The important line to illustrate the need for virtual and override is c->printMe();. Note that the type of c is Base*, however due to polymorphism it is correctly able to call the overridden method from the derived class. The override keyword allows the compiler to enforce that a derived class method matches the signature of a base class's method that is marked virtual. If the override keyword is added to a derived class function, that function does not also need the virtual keyword in the derived class as the virtual is implied.

#include <iostream>

class Base{
public:
virtual void printMe(){
std::cout << "I am the base" << std::endl;
}
};

class Derived: public Base{
public:
void printMe() override {
std::cout << "I am the derived" << std::endl;
}
};

int main() {
Base a;
Derived b;
a.printMe();
b.printMe();
Base* c = &b;
c->printMe();
return 0;
}

The output is

I am the base
I am the derived
I am the derived

What are the differences between overriding virtual functions and hiding non-virtual functions?

What is function hiding?

... is a form of name hiding. A simple example:

void foo(int);
namespace X
{
void foo();

void bar()
{
foo(42); // will not find `::foo`
// because `X::foo` hides it
}
}

This also applies to the name lookup in a base class:

class Base
{
public:
void foo(int);
};

class Derived : public Base
{
public:
void foo();
void bar()
{
foo(42); // will not find `Base::foo`
// because `Derived::foo` hides it
}
};


What is function overriding?

This is linked to the concept of virtual functions. [class.virtual]/2

If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base, a member function vf with the same name, parameter-type-list, cv-qualification, and ref-qualifier (or absence of same) as Base::vf is declared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides Base::vf.

class Base
{
private:
virtual void vf(int) const &&;
virtual void vf2(int);
virtual Base* vf3(int);
};

class Derived : public Base
{
public: // accessibility doesn't matter!
void vf(int) const &&; // overrides `Base::vf(int) const &&`
void vf2(/*int*/); // does NOT override `Base::vf2`
Derived* vf3(int); // DOES override `Base::vf3` (covariant return type)
};

The final overrider becomes relevant when calling a virtual function: [class.virtual]/2

A virtual member function C::vf of a class object S is a final overrider unless the most derived class of which S is a base class subobject (if any) declares or inherits another member function that overrides vf.

I.e. if you have an object of type S, the final overrider is the first overrider you see when traversing the class hierarchy of S back to its base classes. The important point is that the dynamic type of the function-call expression is used in order to determine the final overrider:

Base* p = new Derived;
p -> vf(42); // dynamic type of `*p` is `Derived`

Base& b = *p;
b . vf(42); // dynamic type of `b` is `Derived`


What is the difference between overriding and hiding?

Essentially, the functions in the base class are always hidden by functions of the same name in a derived class; no matter if the function in the derived class overrides a base class' virtual function or not:

class Base
{
private:
virtual void vf(int);
virtual void vf2(int);
};

class Derived : public Base
{
public:
void vf(); // doesn't override, but hides `Base::vf(int)`
void vf2(int); // overrides and hides `Base::vf2(int)`
};

To find a function name, the static type of an expression is used:

Derived d;
d.vf(42); // `vf` is found as `Derived::vf()`, this call is ill-formed
// (too many arguments)


How do they relate to function overloads?

As "function hiding" is a form of name hiding, all overloads are affected if the name of a function is hidden:

class Base
{
private:
virtual void vf(int);
virtual void vf(double);
};

class Derived : public Base
{
public:
void vf(); // hides `Base::vf(int)` and `Base::vf(double)`
};

For function overriding, only the function in the base class with the same arguments will be overriden; you can of course overload a virtual function:

class Base
{
private:
virtual void vf(int);
virtual void vf(double);
void vf(char); // will be hidden by overrides in a derived class
};

class Derived : public Base
{
public:
void vf(int); // overrides `Base::vf(int)`
void vf(double); // overrides `Base::vf(double)`
};

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).

Are there any subtleties in using both the virtual and override keywords in C++11?

Late to the game, but this C++ Core Guideline seems relevant here:

C.128: Virtual functions should specify exactly one of virtual, override, or final


Reason

Readability. Detection of mistakes. Writing explicit virtual, override, or final is self-documenting and enables the compiler to catch mismatch of types and/or names between base and derived classes. However, writing more than one of these three is both redundant and a potential source of errors.

It's simple and clear:

  • virtual means exactly and only "this is a new virtual function."
  • override means exactly and only "this is a non-final overrider."
  • final means exactly and only "this is a final overrider."

C# - Keyword usage virtual+override vs. new

The "new" keyword doesn't override, it signifies a new method that has nothing to do with the base class method.

public class Foo
{
public bool DoSomething() { return false; }
}

public class Bar : Foo
{
public new bool DoSomething() { return true; }
}

public class Test
{
public static void Main ()
{
Foo test = new Bar ();
Console.WriteLine (test.DoSomething ());
}
}

This prints false, if you used override it would have printed true.

(Base code taken from Joseph Daigle)

So, if you are doing real polymorphism you SHOULD ALWAYS OVERRIDE. The only place where you need to use "new" is when the method is not related in any way to the base class version.

Overriding virtual functions and inheritance

Please be patient and read this to get answers to your questions.

Inheritance is a concept in which object of a class inherits the properties and behaviour of object of another class.

Basic Introduction

  • Parent class is also called as base class or super class.
  • Child class is also called as derived class or subclass.
  • An object of a derived class can be referenced through the base class.

For example

#include <iostream>
using namespace std;
class Base {};
class Derived : public Base {};
int main() {
Base *b = new Derived(); // This is completely valid
return 0;
}

Method Overriding in C++

Let's take a basic example

#include <iostream>
using namespace std;
class Base {
public:
void display() { cout << "Base display called\n"; }
};
class Derived : public Base {
public:
void display() { cout << "Derived display called\n"; }
};
int main() {
Base b;
b.display();
Derived d;
d.display();
Base *bptr = &d;
bptr->display();
return 0;
}

Output:

Base display called
Derived display called
Base display called

Now, from the above example you might have guessed that the derived class overrides the base class but this is not the case. The output (3rd line) shows that the base class function is called because the function is not virtual.

Virtual functions in C++

You can make any function of the class virtual by adding the "virtual" keyword at the start of the function.

Lets consider the virtual function example

#include <iostream>
using namespace std;
class Base {
public:
virtual void display() { cout << "Base display called\n"; }
};
class Derived : public Base {
public:
void display() { cout << "Derived display called\n"; }
};
int main() {
Base b;
b.display();
Derived d;
d.display();
Base *bptr = &d;
bptr->display();
return 0;
}

Output:

Base display called
Derived display called
Derived display called

By the above example(line 3 of the output), it is clear that you can achieve method overriding by using the virtual function mechanism in C++.

What is the effect of making a function virtual?

The difference between a normal function and a virtual function is that a normal function is resolved at compile time, also known as static binding, whereas the virtual function is resolved at run time, also known as dynamic binding or late binding. Which method to call (base class display or derived class display method) is resolved at run time since the base class display function is made virtual. You can dive deep into the virtual function mechanism by reading about v-table.

Answers to questions

  1. call(d). I don't quite understand why but it seems that call() can take derived classes of B as an argument.

    • A derived class object can be referenced by a base class
  2. But D::g doesn't override B::g and for the reasons I can't understand.

    • Because g() is not virtual in base class. Only virtual functions can be overridden. v-table has entries to only virtual functions so that they can be overridden at run time.
  3. call(dd)

    • Since f() in DD is a non-const function, therefore f() (non-const f() in DD) is not an overridden method of the parent class D. And since it is being referenced by Base class B, calling b.f() would call the const f() which is being overridden by D. Thus D::f gets printed.
    • If f() was a const method in DD then the following would have happened:
      When f() gets called, the function is searched first in the base class B,
      since f() is virtual, using the v-table pointer, the f() function being overridden in derived class D is resolved. But since f() is not virtual in class D, the overridden f() in DD can't be resolved. Hence D::f gets printed.

      But for g(), the base class itself doesn't have virtual g(), so the overridden functions in their derived classes can't be resolved. Hence, B::g get printed.
  4. The above polymorphism has happened because the derived classes were referenced by their base classes(parent classes), but in the last calls, there is no such thing. All the objects are referenced by their respective classes, and hence their appropriate methods are being called.

One basic logic to think about this is that the function is first looked up in the referencing class, and if it is virtual then the function will be searched in derived classes(if the object being referred is a child class). If the derived classes override, then the derived method will be called, else the base method will be called. You can further extend the concept applied to the base class, to the derived class as well like the check whether the function is virtual or not and then if the function is virtual and the object is derived(child of the derived, grandchild of the base) and so on.

Hope this clarifies.

Does final imply override?

final does not require the function to override anything in the first place. Its effect is defined in [class.virtual]/4 as

If a virtual function f in some class B is marked with the
virt-specifier final and in a class D derived from B a function D::f
overrides B::f, the program is ill-formed.

That's it. Now override final would simply mean

„This function overrides a base class one (override) and cannot be overriden itself (final).“

final on it's own would impose a weaker requirement.
override and final have independent behavior.


Note that final can only be used for virtual functions though - [class.mem]/8

A virt-specifier-seq shall appear only in the declaration of a
virtual member function (10.3).

Hence the declaration

void foo() final;

Is effectively the same as

virtual void foo() final override;

Since both require foo to override something - the second declaration by using override, and the first one by being valid if and only if foo is implicitly virtual, i.e. when foo is overriding a virtual function called foo in a base class, which makes foo in the derived one automatically virtual. Thus override would be superfluous in declarations where final, but not virtual, occurs.

Still, the latter declaration expresses the intent a lot clearer and should definitely be preferred.



Related Topics



Leave a reply



Submit