#include
class base
{
public:
virtual void print (int a)
{
std::cout << \"a: \" << a << \" base\\n\";
}
derived::print does not override any member function in base. It is declared as having a single parameter of type double but the two virtual member functions named print in base are declared as having one and two parameters of type int.
When you use b->print(d), only member functions in base are considered during overload resolution, so only void base::print(int) and void base::print(int, int) are considered. void derived::print(double) can't be found because the compiler has no idea that b points to a derived object.
If derived were to override one of the two print functions declared as virtual member functions in base, then that override would be called at runtime.
(On a somewhat related note, derived::print hides the two base::print member functions, so if you were to try to use one of the base class print functions, e.g., derived().print(1, 1), it would fail. You would need to use a using declaration to make those member functions available during name lookup.)
Overload resolution happens at compile time. Overrides happen at run time.
Therefore, the overload resolution of b->print(d); happens first. This selects Base::print(int) because it's the only one-argument print.
At runtime, b points to a Derived object that has no override for Base::print(int). Therefore, Base::print(int) is still called.
Because double can be automatically converted to an int in the first definition it sees (in the base class)
See explicit keyword or this question