Visibility of function prototypes and declarations

suggest change

In C++, code must be declared or defined before usage. For example, the following produces a compile time error:

int main()
{
    // error: foo is called, but has not yet been declared
    foo(2); 
}

// this definition is not known in main
void foo(int x)
{
}
main.cc: In function 'int main()':
main.cc:4:5: error: 'foo' was not declared in this scope
    4 |     foo(2);
      |     ^~~
exit status 1

There are two ways to resolve this: putting either the definition or declaration of foo() before its usage in main(). Here is one example:

// declare 'foo' function first
void foo(int x) {}

int main()
{
    // OK: 'foo' has been defined, so it can be called here.
    foo(2);
}

However it is also possible to “forward-declare” the function by putting only a “prototype” declaration before its usage and then defining the function body later:

#include <cstdio>

void foo(int);  // Prototype declaration of foo, seen by main
                // Must specify return type, name, and argument list types
int main()
{
    foo(2); // OK: foo is known, called even though its body is not yet defined
}

// Must match the prototype
void foo(int x)
{
    std::printf("foo() was called\n");
}
foo() was called

The prototype must specify the return type (void), the name of the function (foo), and the argument list variable types (int), but the names of the arguments are NOT required.

One common way to integrate this into the organization of source files is to make a header file containing all of the prototype declarations:

// foo.h
void foo(int); // prototype declaration

and then provide the full definition elsewhere:

// foo.cpp --> foo.o
#include "foo.h" // foo's prototype declaration is "hidden" in here
void foo(int x) { } // foo's body definition

and then, once compiled, link the corresponding object file foo.o into the compiled object file where it is used in the linking phase, main.o:

// main.cpp --> main.o
#include "foo.h" // foo's prototype declaration is "hidden" in here
int main() { foo(2); } // foo is valid to call because its prototype declaration was beforehand.
// the prototype and body definitions of foo are linked through the object files

An “unresolved external symbol” error occurs when the function prototype and call exist, but the function body is not defined. These can be trickier to resolve as the compiler won’t report the error until the final linking stage, and it doesn’t know which line to jump to in the code to show the error.

Feedback about page:

Feedback:
Optional: your email if you want me to get back to you:



Table Of Contents