I was reading the linked question which leads me to ask this question.
Consider the following code
int main()
{
string SomeString();
}
When you declare a prototype as you are doing you are basically telling the compiler to wait for the linker to resolve it. Depending where you write the prototype the scoping rules apply. There is nothing technically wrong writing the prototype inside your main() function (although IMHO a bit messier), it just means that the function is only locally known inside the main(). If you would have declared the prototype at the top of your source file (or more commonly in a header file), the prototype/function would be known in the whole source.
string foo()
{
string ret = someString(); // Error
return ret;
}
int main(int argc,char**argv)
{
string someString();
string s = somestring(); // OK
...
}
As to why your declaration of
void f() {
void g(); g();
}
is better than this one
void g();
void f() {
g();
}
It's generally good if you keep declarations as local as possible, so that as few name clashes as possible result. I say it's arguable whether declaring a function locally (this way) is really fortunate, as i think it's still better to ordinary include its header and then go the "usual" way, which is also less confusing to people not knowing about that. Sometimes, it's also useful to work around a shadowed function
void f() {
int g;
// oops, ::g is shadowed. But we can work around that
{
void g(); g();
}
}
Of course, in C++ we could call function g
using its_namespace::g()
- but in the old days of C, that wouldn't have been possible, and that thing allowed the programmer to still access the function. Also note that while syntactically it is not the same, semantically the following does also declare a function within a local scope, that actually targets a different scope.
int main() {
using std::exit;
exit();
}
As a side note, there are more situations like that where the target scope of a declaration is not the scope where that declaration appears in. In general, the entity you declare becomes a member of the scope in which the declaration appears. But that's not always the case. Consider for example friend declarations, where that thing happens
struct X { friend void f() { std::cout << "WoW"; } };
int main() { void f(); f(); } // works!
Even though the function declaration (and definition!) of f
happened within the scope of X
, the entity (the function itself) became a member of the enclosing namespace.
This is a convention from C -- like many -- which C++ has adopted.
The ability to declare a function inside another function in C is a decision that most programmers probably consider regrettable and unnecessary. Particularly with modern OOP design where function definitions are comparatively smaller than they are in C.
If you would like to have functions that only exist in the scope of another function, two options are boost::lambda and C++1x lambda.
Just as a side note, C++03 does have a roundabout way of defining local functions. It requires abusing the local-class feature:
int main()
{
struct Local
{
static string Some()
{
return "";
}
};
std::cout << Local::Some() << std::endl;
}
Your prototype is just 'Forward Declaration'. Please check out the Wikipedia article.
Basically, it tells the compiler "don't be alarmed if the label 'SomeFun' is used in this way". But your linker is what's responsible for finding the correct function body.
You can actually declare a bogus prototype, e.g. 'char SomeFun()' and use it all over your main. You will only get an error when your linker tries to find the body of your bogus function. But your compiler will be cool with it.
There are lots of benefits. You have to remember the function body is not always in the same source code file. It can be in a linked library.Also, that linked library may be have a specific 'link signature'.Use conditional defines you may even select the correct link signature at build time using your scoped prototypes.Although most people would use function pointers for that instead.
Hope this helps.
Function prototypes are hints for the compiler. They indicate that the functions are implemented somewhere else, if not already discovered. Nothing more.