The function declaration gives the compiler enough information to generate a call to that function.
The compiler then generates an object file that specifies the names (which, in the case of C++ are mangled to specify the arguments, namespace, cv-qualifiers, etc.) of external functions to which that object file refers (along with another list of names it defines).
The linker then takes all those object files, and tries to match up every name that something refers to but doesn't define with some other object file that defines the same name. Then it assigns and fills in addresses, so where one object file refers to nameX, it fills in the address it's assigning to nameX from the other file.
At least in a typical case, the object files it looks at will include a number of libraries (standard library + any others you specify). A library is basically just a collection of object files, shoved together into a single file, with enough data to index what data is which object file. In a few cases, it also includes some extra meta-data to (for example) quickly find an object file that defines a specific name (obviously handy for the sake of faster linking, but not really an absolute necessity).
If there are two or more functions with exactly the same mangled name, then your code has undefined behavior (you're violating the one definition rule). The linker will usually give an error message telling you that nameZ was defined in both object file A and object file B (but the C++ standard doesn't really require that).