Why "BaseClass::init" is being called instead of "BaseClass::init" ?
Because init is a non-virtual member function. To have the desired effect, you need to make init a virtual member function as shown below:
class BaseClass
{
public:
BaseClass() {}
//NOTE THE VIRTUAL KEYWORD HERE
virtual void init(const int object) { cout<<"BaseClass::init"<<endl; }
//other member function here as before
};
Demo
I though we need virtual functions only when calling through a pointer.
Note that the statement init(object); is equivalent to writing
this->init(object); //here `this` is a pointer
When you wrote:
d.run(5);
In the above statement, first the address of object d is implicitly passed as the first argument to the implicit this parameter of member function run. The type of this implicit this parameter is BaseClass* and this happens due to derived to base conversion. Now, the call init(object); is equivalent to this->init(object);. But since init is a non-virtual member function, the call is resolved at compile time meaning the base class init will be called.
Basically when a member function is called with a derived class object, the compiler first looks to see if that member exists in the derived class. If not, it begins walking up the inheritance chain and checking whether the member has been defined in any of the parent classes. It uses the first one it finds. This means for the call d.run(5) the search for a member function named run starts inside the derived class. But since there is no function named run inside derived class, the compiler looks into the direct base class BaseClass and finds the member function named run. So it stops its search and uses this found run member function. And as i said, in your example, init is non-virtual and so the call is resolved at compile time to the base class run.
On the other hand, if we make init to be a virtual member function, then this call will be resolved at run-time meaning the derived class init will be called.