If there is no function overloading, the function name serves as the address of the function code, and when a function is being called, its address is easy to find using its
The compiler can look at the call, and match that against the known existing overloaded implementations, and pick the right one. No need for a dynamic table, it's all perfectly doable statically at compile-time.
Update: removed my attempt at illustrating the concept by showing differently-named functions that the compiler can choose between.
Even if no function overload, compilers usually mangle function and variable names. It is called name mangling. It happens in both C and C++. Function name can be decorated by notably (1) calling convention, (2) C++ function overloading, (3) class member function.
GNU binutil c++filt
can undecorate this mangled name, and in Windows, there is UnDecorateSymbolName