What is overriding:
The redefinition of a virtual function in a derived class is known as overriding. Consequently, to override a virtual function of base class, the functions in derived class must have exactly same signatures as they were there in the base class. Please note that the use of override keyword is important here.
What are Virtual Functions:
Firstly, to make a member function as virtual, the class simply precedes the declaration of the function with the keyword virtual. Only the declaration of such functions needs the virtual keyword, not the definition. If a function is declared as virtual in the base class, then it becomes virtual in all the derived classes. Although writing virtual keyword for functions in derived class functions is good practice and improves readability.
Where is the Problem:
Programmers sometimes make mistake in writing derived class or misunderstand the specifications. The way C++ compiler work is that, it will not consider given function in derived class as “overriding” and silently ignore the derived class function when it find that the signature of derived class function is not matching with function in base class.
Therefore, the compiler on its own cannot decide, if mismatch is is a genuine mistake or the mismatch was intentional.
Such issues may lead to false positives. Consider following example.
#include <iostream> //main header
using namespace std;//for namespace
class MFBase
{
public:
virtual void print_function(unsigned int i)
{
cout << i << endl;
}
};
class MFDerived : public MFBase
{
public:
virtual void print_function(int i)
{
cout << "The given number is "
<< i
<< endl;
}
};
int main()
{
MFBase *b = new MFDerived;
b->print_function(5);
delete b;
return 0;
}
Clearly, the implementation in derived class has a different argument type, it is int and not unsigned int. Therefore, the compiler will choose to ignore the Derived implementation and always the Base version of fun1 will be called.
The output of the given program is shown below and this is not what the programmer may expect.
5
Apart from the argument type as explained above, there are other conditions which lead to similar issues. This means, in such cases, compiler matches and silently ignores in similar way are:
Constness
void MFBase::fun1( );
void MFDerived::fun1( ) const;
L-value & R-value qualifier types
void MFBase::fun1( ) & ;
void MFDerived::fun1( ) &&;
How Override Keyword Helps: The use of override keyword (in Derived classes) solves all these problems. This is because, it will force the compiler to look for proper overriding match and will generate an error if no match is found.
#include <iostream> //main header using namespace std;//for namespace class MFBase { public: virtual void print_function(unsigned int i) { cout << i << endl; } }; class MFDerived : public MFBase { public: virtual void print_function(int i) override { cout << "The given number is " << i << endl; } }; int main() { MFBase *b = new MFDerived; b->print_function(5); delete b; return 0; }
Following error will be generated by compiler: