Due to the linear mentality of the C++ compiler, each function call requires a lookup of all functions defined up to this point; if that function is not found, an error is thrown. The compiler doesn't care about what the function does, it just wants to make sure you've called it correctly.
Consider:
Code:
#include <iostream>
int main()
{
output();
return 0;
}
void output()
{
std::cout << "C++ is too linear for me." << std::endl;
}
The compiler runs - though sometimes seemingly saunters - through the code, notices output() and proceeds to perform a lookup of the "output" function. Alas, this function has not been defined at this point (it is defined later!) so the compiler must throw an error; metaphorically, it refuses to use a power-drill when it hasn't been taught how to operate it, and it arguably doesn't need to know how it works, just how to use it.
But you're probably thinking, well, that's stupid. The function's right there, why can't it just search the entire file for it?
Consider if, hypothetically, it did search the file for it. It works great in simple scenarios such as these, but what happens when your function is in a separate file in a separate library amongst a forest of files numbering in the thousands? A quick scan here is an oxymoron. Now we have to resort to some form of a cached function list which we have to keep up-to-date constantly with every build of our app. And what if there's a function in a dll or lib that we don't have direct access to? Now we're just plain hosed.
And so function prototypes are born.