If you are using polymorphism, that is, treating a DerivedClass as a BaseClass using either a reference or a pointer, then regular functions can be overloaded but not virtually overridden.
#include <iostream>
class BaseClass
{
public:
void myFunc() //Can't be overridden, can be overloaded and hidden.
{
std::cout << "BaseClass::myFunc() called" << std::endl;
}
virtual void myVirtualFunc() //Can be overridden, but doesn't have to be.
{
std::cout << "BaseClass::myVirtualFunc() called" << std::endl;
}
virtual void myPureVirtualFunc() = 0; //Must be overridden.
};
class DerivedClass : public BaseClass
{
public:
void myFunc() //This is an overload, not an override (because Base's myFunc() is not virtual). Polymorphism will not call this function.
{
std::cout << "DerivedClass::myFunc() called" << std::endl;
}
virtual void myVirtualFunc()
{
std::cout << "DerivedClass::myVirtualFunc() called" << std::endl;
}
virtual void myPureVirtualFunc()
{
std::cout << "DerivedClass::myPureVirtualFunc() called" << std::endl;
}
};
int main()
{
//BaseClass baseClass; //Can't be constructed because of pure-virtual.
DerivedClass derivedClass;
BaseClass &derivedPretendingToBeBase = derivedClass;
derivedClass.myFunc(); //Calls DerivedClass::myFunc().
derivedClass.myVirtualFunc(); //Calls DerivedClass::myVirtualFunc().
derivedClass.myPureVirtualFunc(); //Calls DerivedClass::myPureVirtualFunc().
derivedPretendingToBeBase.myFunc(); //Calls BaseClass::myFunc(), because it's not virtual.
derivedPretendingToBeBase.myVirtualFunc(); //Calls DerivedClass::myVirtualFunc(), because it IS virtual and overridden.
derivedPretendingToBeBase.myPureVirtualFunc(); //Calls DerivedClass::myPureVirtualFunc(), because it is virtual and overridden.
return 0;
}
See the code results
here.
If you are using polymorphism, and treating all your derived classes as base classes, the Base function will always be called as long as it's not virtual.
If you aren't using polymorphism, and are using a derived class directly, the derived's functions will always be called, unless it doesn't have that function, then it'll look at any inherited classes and check if they have that function.
If you want to enforce that a base class' functions are never
overridden don't make it virtual - but it could still be
overloaded, and be
hidden by any derived classes. But this is never a problem when treating your derived classes as Base pointers or references.
All 'final' does is make sure that a virtual function is no longer overridden, in a chain like this:
class Base
{
virtual void myFuncA() { }
virtual void myFuncB() { }
}
class DerivedA : public Base
{
virtual void myFuncA() { }
virtual void myFuncB() final { }
}
class DerivedB : public DerivedA
{
virtual void myFuncA() { }
virtual void myFuncB() { } //Compile error! This virtual function was declared 'final' earlier up the inheritance tree. It can't be overridden further.
}
So, given:
DerivedB inherits DerivedA inherits Base
Base *poly = &derivedB;virtual functions: Starting at the 'real' class (DerivedB), works up until an implementation is found. (Checks DerivedB, then DerivedA, then Base)
Non-virtual functions: Starting at the reference/pointer class (Base), looks in that class, and up the inheritance tree at any classes it inherits from, but does not look down the inheritance tree to any classes that derive from it.
If you are using a class directly (treating a DerivedClass as a DerivedClass, and not as a Base pointer), then you can't stop a user from overriding a function unless you declare it virtual AND final in the BaseClass... which is kinda counter-intuitive and questionable. Virtual implies it can be overridden, final says that it can't be overridden (from this point onward), so a BaseClass that does them both is like saying Yes and No at the same time. It'd work, but why would it be needed?
If Derived wants to override it, it won't harm anything... unless you're using polymorphism. If you are using polymorphism, making it non-virtual solves the problem.