The “Three Steps” to Resolving an Unqualified Function Call (by Leor Zolman, May 2015) Given: obj is an object, ptr is a pointer, ref is a reference, f is a member function and the terms: static type: the type an object has been declared to be, or the type a pointer or reference has been declared to point/refer to dynamic type: the type a pointer or reference actually points to Then any call of the form: obj.f(…); ptr -> f(…); [Note: f(…); within a member function actually means this->f(…);] ref.f(…); is resolved by the compiler in three steps, as follows: Step 1: Ask the question, “Is f(…) in scope within the static type of obj/ptr/ref?” If the answer is “No”: the code is illegal; compile error. If the answer is “Yes”, the code is valid. If the call is on an object (not a pointer or reference): The call is statically bound (determined at compile/link time) and the function called is the one identified. Else the call is on a pointer or reference. Go to Step 2. Step 2: Ask the question, “In the scope of the static type of obj/ptr/ref, is f(…) virtual?” If the answer is “No”: the call is statically bound (determined at compile/link time) and the function that gets called is the one identified in Step 1. If the answer is “Yes”, go on to step 3. Step 3: The call is dynamically bound (determined through a virtual call at runtime), and the function that gets called is the one with that same signature in the scope of the dynamic type of the pointer or reference.