I've my answer in form of a conversation to be a better read:
Why do we need virtual functions?
Because of Polymorphism.
What is Polymorphism?
The fact that a base pointer can also point to derived type objects.
How does this definition of Polymorphism lead into the need for virtual functions?
Well, through early binding.
What is early binding?
Early binding(compile-time binding) in C++ means that a function call is fixed before the program is executed.
So...?
So if you use a base type as the parameter of a function, the compiler will only recognize the base interface, and if you call that function with any arguments from derived classes, it gets sliced off, which is not what you want to happen.
If it's not what we want to happen, why is this allowed?
Because we need Polymorphism!
What's the benefit of Polymorphism then?
You can use a base type pointer as the parameter of a single function, and then in the run-time of your program, you can access each of the derived type interfaces(e.g. their member functions) without any issues, using dereferencing of that single base pointer.
I still don't know what virtual functions are good for...! And this was my first question!
well, this is because you asked your question too soon!
Why do we need virtual functions?
Assume that you called a function with a base pointer, which had the address of an object from one of its derived classes. As we've talked about it above, in the run-time, this pointer gets dereferenced, so far so good, however, we expect a method(== a member function) "from our derived class" to be executed! However, a same method(one that has a same header) is already defined in the base class, so why should your program bother to choose the other method? In other words I mean, how can you tell this scenario off from what we used to see normally happen before?
The brief answer is "a Virtual member function in base", and a little longer answer is that, "at this step, if the program sees a virtual function in the base class, it knows(realizes) that you're trying to use polymorphism" and so goes to derived classes(using v-table, a form of late binding) to find that another method with the same header, but with -expectedly- a different implementation.
Why a different implementation?
You knuckle-head! Go read a good book!
OK, wait wait wait, why would one bother to use base pointers, when he/she could simply use derived type pointers? You be the judge, is all this headache worth it? Look at these two snippets:
//1:
Parent* p1 = &boy;
p1 -> task();
Parent* p2 = &girl;
p2 -> task();
//2:
Boy* p1 = &boy;
p1 -> task();
Girl* p2 = &girl;
p2 -> task();
OK, although I think that 1 is still better than 2, you could write 1 like this either:
//1:
Parent* p1 = &boy;
p1 -> task();
p1 = &girl;
p1 -> task();
and moreover, you should be aware that this is yet just a contrived use of all the things I've explained to you so far. Instead of this, assume for example a situation in which you had a function in your program that used the methods from each of the derived classes respectively(getMonthBenefit()):
double totalMonthBenefit = 0;
std::vector<CentralShop*> mainShop = { &shop1, &shop2, &shop3, &shop4, &shop5, &shop6};
for(CentralShop* x : mainShop){
totalMonthBenefit += x -> getMonthBenefit();
}
Now, try to re-write this, without any headaches!
double totalMonthBenefit=0;
Shop1* branch1 = &shop1;
Shop2* branch2 = &shop2;
Shop3* branch3 = &shop3;
Shop4* branch4 = &shop4;
Shop5* branch5 = &shop5;
Shop6* branch6 = &shop6;
totalMonthBenefit += branch1 -> getMonthBenefit();
totalMonthBenefit += branch2 -> getMonthBenefit();
totalMonthBenefit += branch3 -> getMonthBenefit();
totalMonthBenefit += branch4 -> getMonthBenefit();
totalMonthBenefit += branch5 -> getMonthBenefit();
totalMonthBenefit += branch6 -> getMonthBenefit();
And actually, this might be yet a contrived example either!