In C++, one way to get late/dynamic binding is to use function pointers we can also use virtual functions.
But don't know about the early/static binding.
In C++, one way to get late/dynamic binding is to use function pointers we can also use virtual functions.
But don't know about the early/static binding.
Most compilers will statically bind something like this:
int foo()
{
return 1;
}
typdef int (*intFunc)();
int main()
{
intFunc f = &foo;
cout << f();
}
I would think so. If you have the function statically defined, you take its address, and assign it to a field in your class. When the program compiles, the linker determines where the function should live and you also have already set your reference?
Am I missing the actual point of the question?
You can't get static binding with a pointer. Technically it's not even "bound" -- it's just the address of some function that you then need to call at runtime. For static binding, the compiler would need to know the address of the function in advance to put it directly in the output machine code, but the value of a pointer is not (usually) known until runtime.
If the compiler can guarantee that a pointer value is invariant, or if it can narrow down the value of a pointer at a particular point in execution, then it could possibly optimize things and bind the call statically:
void foo() {
cerr << "foo!" << endl;
}
int main(int argc, char **argv) {
void (*f)() = &foo;
f(); // can statically bind here... but why use a pointer?
}
But this is a toy example. If the compiler can figure out that your pointer always points to the same function, then one has to wonder why you're using a pointer.
Here's a toy ...
extern void verbose() ;
extern void terse() ;
const bool debug1 = false;
extern bool debug2;
void toy() {
void (*f)() = debug1 ? verbose : terse ;
(*f)();
f = debug2 ? verbose : terse ;
(*f)();
return;
}
... and here's how the implementers of Intel 11 C++ for Linux interpret it (comments removed):
# mark_begin;
.globl _Z3toyv
_Z3toyv:
..B1.1: # Preds ..B1.0
call _Z5tersev #7.3
..B1.2: # Preds ..B1.1
movzbl debug2, %eax #8.7
movl $_Z7verbosev, %edx #8.3
movl $_Z5tersev, %ecx #8.3
cmpl $0, %eax #8.3
cmovne %edx, %ecx #8.3
call *%ecx #9.3
..B1.3: # Preds ..B1.2
ret #10.3
.align 16,0x90
# mark_end;
The first call depends on debug1
, which is a known-at-compile-time constant. Intel breezes through the ternary operator and reduces it to "call terse" in #7.3.
The second call depends on debug2
, which is extern, in some other compilation unit. Intel, figuring that given the hapless state of the human condition, any bool is more likely to be false than true, moves the address of terse
into ecx and verbose
into edx, compares the runtime value of debug2
to zero, and if it's not zero, moves edx to ecx, then calls whatever is in ecx. Note that if you know a priori that debug2 is in fact going to be biased towards truth and that this code is in a critical loop, there may be a compiler-dependent optimization possibility.