Functions
Function Pointers
Pointers to functions for callbacks and dynamic dispatch
Interview: Foundation for callbacks, command patterns, and understanding how virtual dispatch works internally
Function Pointers
A function pointer is a variable that stores the address of a function. Just as a data pointer holds the address of a memory location, a function pointer holds the address of executable code. Calling through a function pointer transfers execution to that address — the foundation of callbacks, dispatch tables, and plugin architectures.
Syntax and Declaration
The syntax for function pointer types is notoriously noisy: ReturnType (*pointerName)(ParamTypes). The parentheses around *pointerName are mandatory — without them, int *f(int) declares a function returning int*, not a pointer to a function. Use using or typedef to create readable type aliases.
Function Pointers vs std::function
Raw function pointers can only point to free functions and static member functions — they cannot capture state. std::function is a type-erased wrapper that can hold any callable (lambdas, member functions, functors) at the cost of a virtual dispatch overhead. For performance-critical callbacks, raw function pointers or templates are preferred.
Virtual Function Tables (vtable)
C++ implements virtual function dispatch using an array of function pointers called the vtable. Each polymorphic class has a vtable, and each object holds a hidden vptr pointing to it. A virtual call is essentially a function pointer lookup: vptr[vtable_index](args). Understanding function pointers demystifies how virtual dispatch works at the machine level.
Interview Corner
Q: What is the difference between a function pointer and std::function?
A: A raw function pointer can only point to free functions or static members — it cannot capture state. std::function is a type-erased, heap-allocating wrapper that accepts any callable including stateful lambdas. The trade-off: raw function pointers are zero-overhead (just a pointer call), while std::function involves indirection and possible heap allocation. For hot paths, prefer raw pointers or templates; for flexible APIs, use std::function.
Q: How does C++ implement virtual function dispatch internally?
A: Each polymorphic class has a vtable — a static array of function pointers. Each polymorphic object contains a hidden vptr (pointer to its class's vtable). A virtual call like base->method() compiles to: load vptr from object, index into vtable, call the function pointer. This is exactly one extra indirection compared to a direct call — that's the cost of runtime polymorphism.
Common Pitfalls
- Calling a null function pointer: Dereferencing a null function pointer is undefined behavior (usually a crash). Always validate before calling:
if (fp) fp(args); - Incompatible signatures: Casting a function pointer to an incompatible signature and calling through it is undefined behavior. The parameter types and return type must match exactly.
- Non-static member functions: Pointers to non-static member functions have a different type:
ReturnType (ClassName::*ptr)(Params). They require an object instance to call through.
Best Practices
- Use
using FuncType = ReturnType(*)(Params);to create readable type aliases for function pointer types. - Prefer templates with callable parameters in new code — they accept lambdas, functors, and function pointers without overhead:
template<typename F> void apply(F f); - Use
std::functiononly when you need to store different callables in a container or across ABI boundaries.