At compile time, the compiler cannot identify the function that is called by the statement person->computePay(), since it could be any of several different functions. The compiler must evaluate the statement at run time, when it can tell what type of object person points to. This is known as “late binding” or “dynamic binding.” This behavior is very different from function calls in C, or nonvirtual function calls in C++. In both cases, the function call statement is translated at compile time into a call to a fixed function address. This is known as “early binding” or “static binding.”
Dynamic binding lets you modify the behavior of code that has already been compiled. You can make an existing module handle new types without having to modify the source and recompile it.
For example, suppose that the function computePayroll and all the other employee-database functions have been compiled into a module called EMPUTIL.OBJ. Now suppose that you want to define a new type of employee called a Consultant, and use it with all the existing employee-database functions.
You don't have to modify the source code for computePayroll or any other functions in EMPUTIL.OBJ. You simply derive Consultant from the Employee class, define its member functions in a new source file CONSULT.CPP, and compile it into CONSULT.OBJ. Then you modify your program's user interface to allow users to enter information on consultants. After you've recompiled that portion of the program, you can link it with CONSULT.OBJ and EMPUTIL.OBJ to produce a new executable.
You can then add Consultant objects to the EmployeeList object that the program already maintains. When you compute the payroll, the computePayroll function works just it did before. If there are any Consultant objects in the list, the statement person->computePay() automatically calls Consultant::computePay, even though that function didn't exist when the statement was first compiled.
Dynamic binding lets you provide a library of classes that other programmers can extend even if they don't have your source code. All you need to distribute are the header files (the .H files) and the compiled object code (.OBJ or .LIB files) for the hierarchy of classes you've written and for the functions that use those classes. Other programmers can derive new classes from yours and redefine the virtual functions you declared. Then the functions that use your classes can handle the classes they've defined.