Compiler determines address of every variables and methods while compiling source code not while executing the binary (it is applicable to virtual methods and dynamic link libs as well). Now the question is when address is determined at compile time, how run time binding works?
Here is the answer:
Whenever a method is called, compiler puts machine level code (‘call’ instruction in assembly level language) and supplies method’s address to call that method. Let’s take an simple example to understand this:
class test {
public:
void compile_time_binding_method()
{ printf("\nIn compile_time_binding_method() method"); }
virtual void run_time_binding_method()
{ printf("\nIn compile_time_binding_method() method"); }
};
Here, the ‘test’ class contain a virtual method ‘run_time_binding_method()’ and a non-virtual method ‘compile_time_binding_method()’.
Let’s create an object, its reference and a pointer to point to the created object:
test a; // Created a object of test class
test &refA = a; // Reference of object ‘a’
test *ptrA = &a; // Pointer of object ‘a’
Let’s call methods using object:
What do think calling a virtual method via its object will be a run time binding? If your answer is no, you are correct. When any method is called using its object, compiler is sure about the method to call. So dynamic binding/call is not at all required here even if a virtual method is being called. You can verify this by reviewing generated dis-assembly code.
a.compile_time_binding_method();
lea ecx,[a] // Dis-assembly code
call test::compile_time_binding_method (41118Bh)
a.run_time_binding_method();
lea ecx,[a] // Dis-assembly code
call test::run_time_binding_method (4110EBh)
In above generated dis-assembly code, we can see that the address of both the methods are hard coded (address determined by compiler while compiling the source code) to resolve the call. This hard coded address will never change (unless you modify and re-compile the source code) in the binary. Such binding/linking is known as static binding/linking (or compile time binding).
These calls are static calls because address is hard coded with machine code generated by compiler (same as ‘call
Let’s call methods using its pointer:
For non-virtual methods:
ptrA->compile_time_binding_method();
mov ecx,dword ptr [ptrA]
call test::compile_time_binding_method (41118Bh)
ptrA->run_time_binding_method();
mov eax,dword ptr [ptrA] //getting object's address
mov edx,dword ptr [eax] //getting VTABLE's address
mov esi,esp
mov ecx,dword ptr [ptrA]
//The following line will gets the address of
//run_time_binding_method() from VTABLE
mov eax,dword ptr [edx]
call eax // will call run_time_binding_method
cmp esi,esp
call @ILT+370(__RTC_CheckEsp) (411177h)
Let’s call methods using its reference:
As reference is nothing but an implicit pointer to the object, the method calls via reference is same as method calls via pointer:
refA.compile_time_binding_method();
mov ecx,dword ptr [refA]
call test::compile_time_binding_method (41118Bh)
refA.run_time_binding_method();
mov eax,dword ptr [refA]
mov edx,dword ptr [eax]
mov esi,esp
mov ecx,dword ptr [refA]
mov eax,dword ptr [edx]
call eax
cmp esi,esp
call @ILT+370(__RTC_CheckEsp) (411177h)
As I am not an author by profession, I might not have explained it in a best way J. Please help me make it best by raising your question/doubt.