12.4 — Early binding and late binding

In this lesson and the next, we are going to take a closer look at how virtual functions are implemented. While this information is not strictly necessary to effectively use virtual functions, it is interesting. Nevertheless, you can consider both sections optional reading.

When a C++ program is executed, it executes sequentially, beginning at the top of main(). When a function call is encountered, the point of execution jumps to the beginning of the function being called. How does the CPU know to do this?

When a program is compiled, the compiler converts each statement in your C++ program into one or more lines of machine language. Each line of machine language is given its own unique sequential address. This is no different for functions -- when a function is encountered, it is converted into machine language and given the next available address. Thus, each function ends up with a unique address.

Binding refers to the process that is used to convert identifiers (such as variable and function names) into addresses. Although binding is used for both variables and functions, in this lesson we’re going to focus on function binding.

Early binding

Most of the function calls the compiler encounters will be direct function calls. A direct function call is a statement that directly calls a function. For example:

Direct function calls can be resolved using a process known as early binding. Early binding (also called static binding) means the compiler (or linker) is able to directly associate the identifier name (such as a function or variable name) with a machine address. Remember that all functions have a unique address. So when the compiler (or linker) encounters a function call, it replaces the function call with a machine language instruction that tells the CPU to jump to the address of the function.

Let’s take a look at a simple calculator program that uses early binding:

Because add(), subtract(), and multiply() are all direct function calls, the compiler will use early binding to resolve the add(), subtract(), and multiply() function calls. The compiler will replace the add() function call with an instruction that tells the CPU to jump to the address of the add() function. The same holds true for subtract() and multiply().

Late Binding

In some programs, it is not possible to know which function will be called until runtime (when the program is run). This is known as late binding (or dynamic binding). In C++, one way to get late binding is to use function pointers. To review function pointers briefly, a function pointer is a type of pointer that points to a function instead of a variable. The function that a function pointer points to can be called by using the function call operator (()) on the pointer.

For example, the following code calls the add() function:

Calling a function via a function pointer is also known as an indirect function call. The following calculator program is functionally identical to the calculator example above, except it uses a function pointer instead of a direct function call:

In this example, instead of calling the add(), subtract(), or multiply() function directly, we’ve instead set pFcn to point at the function we wish to call. Then we call the function through the pointer. The compiler is unable to use early binding to resolve the function call pFcn(x, y) because it can not tell which function pFcn will be pointing to at compile time!

Late binding is slightly less efficient since it involves an extra level of indirection. With early binding, the CPU can jump directly to the function’s address. With late binding, the program has to read the address held in the pointer and then jump to that address. This involves one extra step, making it slightly slower. However, the advantage of late binding is that it is more flexible than early binding, because decisions about what function to call do not need to be made until run time.

In the next lesson, we’ll take a look at how late binding is used to implement virtual functions.

12.5 -- The virtual table
12.3 -- Virtual destructors, virtual assignment, and overriding virtualization

77 comments to 12.4 — Early binding and late binding

  • Nirbhay

    So in case of late binding example, when the user inputs "op" value(run time), the CPU (not the compiler) will know which function pFcn is pointing to and therefore it is runtime/dynamic/late binding. I understand.

    But in case of the first example(static binding), also when the user enters "op" value, only then the CPU will know which is the address of the result(calculated by giving the "op" value at run time)whose stored value the CPU needs to print out.. so how is it also not late binding?

    Please explain. I feel this answer can really clear my way to understand these bindings and therefore Virtual functions :)


    • You've got to look at the function call itself, not how it gets there.

      The compiler can't know which function is going to be called in the end, because it depends on the user's input.
      But no matter which value `result` has, the compiler knows which function to call in that specific case.

      In the second example,

      the compiler doesn't know what `pFcn` is, it could be anything and its value can change during run-time.

      Imagine you had 3 lamps. 1 red, 1 green, 1 blue. Those are our functions, `add`, `subtract` and `multiply`.

      In the first example, you have 3 buttons. Again 1 red, 1 green, 1 blue. They're wired to their respective lamps.
      In front of you is a giraffe and it will shout red, green, or blue. You then press the button that the giraffe said. You don't yet know what the giraffe is going to say, but you know how to react to it and what each button does. That's early binding.

      In the second example, you have 1 white button and 1 wire. That's `pFcn`. You know how to use it, but you don't know what the giraffe is going to say, so you can't wire it up yet (You could, but it might be wrong). When the giraffe shouts a color, you plug in the cable and push the button. That's late binding.

  • Vitali

    "...The compiler is unable to use early binding to resolve the function call pFcn(x, y) because it can not tell which function pFcn will be pointing to at compile time!.." but when we enter "op" value then it will be clear for the compiler to what function "pfcn" will be why late binding?

    • Alex

      When we enter "op" value, the program has already been compiled and is now actually running. The compiler has no role to play at this point.

  • Abhay Gupta

    class parent
      int x;
      void fun()
        cout<<"Inside parent\n";
    class child
      int y;
      void fun()
        cout<<"Inside child\n";

    int main()
      parent *p;
      parent ob1;
      child  ob2;


    in main function we have written p=&ob2;

    then why compiler can't determine which object it is pointing at compile time?

    my doubt is " parent ob1  declares memory for ob1 at compile time (virtual address) and at run time this memory is mapped to physical address and same does for statement child ob2 then why the statement p=&ob2 can not determine address of ob2 at compile time and why do we need late binding?"

    please reply as soon as possible

    • Assuming your compiler uses the stack to store @ob2:
      The base address of the stack doesn't have to be the same every time you run the program. @ob2 will be stored at base+XYZ. The compiler knows XYZ, but base is unknown at compile-time. When you run the program, base will be added to all address references automatically when they're used.
      Same goes for global variables. Those aren't stored on the stack, but their section is also offset by a value unknown at compile-time.

  • Zablas

    How do early and late binding tie in with the stack? I remember you writing, that when a function is called, a function frame is pushed onto the stack. What happens first? The binding or the push onto the stack?

    • Alex

      First, the function to be called needs to be determined (via early or late binding). Then the stack frame is pushed onto the stack.

  • Roy

    about "Late Binding". from the exapmle, we know that which function to call, maybe call a function directly, or call a function depends on input choice. what i mean is we can know the correct address to call at complier time as long as the complier is strong. so is there really late binging?

    • nascardriver

      Hi Roy!

      All virtual functions are called using late binding, you can even replace the vTable at runtime. See the next lesson for more information about vTables.

  • Shashank More

    "the compiler converts each statement in your C++ program into one or more lines of machine language.Each line of machine language is given its own unique sequential address" (in Early binding).

    But at the compile time how can the compiler set the address of the functions because addresses are resolved or given at the run time not at compile time(This is what we learned in Pointers)????

    • Alex

      Statements, functions, and static variables are all known at compile time, so the compiler can determine what address they will occupy.

      Dynamic variables have their addresses set at runtime (because the OS allocates the memory).

      Functions aren't dynamic variables, so their addresses aren't subject to this rule.

      • Shashank More

        what about local variable?? Is their address is also known at the compile time?? I don't think so!!

        • Alex


          You're misunderstanding the issue. The compiler doesn't need to know the actual memory address the variable will end up with. That's governed by a lot of factors, including where in memory the OS decides to load the program in. Simplifying a bit, the compiler only needs to know where the identifier lives relative to the start of the program. In the case of a local variable int x, the compiler only needs to know where x lives relative to the start of the stack frame.

Leave a Comment

Put all code inside code tags: [code]your code here[/code]