开发者

Two main functions

开发者 https://www.devze.com 2022-12-26 20:06 出处:网络
Can we have two main() f开发者_JAVA技巧unctions in a C++ program?The standard explicitly says in 3.6.1:

Can we have two main() f开发者_JAVA技巧unctions in a C++ program?


The standard explicitly says in 3.6.1:

A program shall contain a global function called main, which is the designated start of the program. [...] This function shall not be overloaded.

So there can one only be one one main function in the global scope in a program. Functions in other scopes that are also called main are not affected by this, there can be any number of them.


Only one function can be named main outside of any namespace, just as for any other name. If you have namespaces foo and bar (etc) you can perfectly well have functions named foo::main, bar::main, and so on, but they won't be treated as anything special from the system's point of view (only the function named main outside of any namespace is treated specially, as the program's entry point). Of course, from your main you could perfectly well call the various foo::main, bar::main, and so on.


Yes! Why not?

Consider the following code:

 namespace ps
 {
     int main(){return 0;}
 }

 int main()
 {
     ps::main();
 }

Its ::main() that will be called during execution.


You can't overload main() in the global scope.


A program can only have one entry point, but of course that one main() function can call out to other functions, based on whatever logic you care to specify. So if you are looking for a way to effectively compile two or more programs into a single executable, you can do something like this:

int main(int argc, char ** argv)
{
   if (argc > 0)  // paranoia
   {
           if (strstr(argv[0], "frogger")) return frogger_main(argc, argv);
      else if (strstr(argv[0], "pacman"))  return pacman_main(argc, argv);
      else if (strstr(argv[0], "tempest")) return tempest_main(argc, argv);
   }

   printf("Hmm, I'm not sure what I should run.\n");
   return 10;
}

... then just rename your 'other' main() functions to frogger_main(), pacman_main(), or whatever names you care to give them, and you'll have a program that runs as Frogger if the executable name has the word 'frogger' in it, or runs as PacMan if the executable has the name 'pacman' in it, etc.


In one single program, only one entry point is allowed.


Ooh, trick question!

Short answer: "It depends."

Long answer: As others have pointed out, you can have multiple functions named main so long as they are in different namespaces, and only the main in the root namespace (i.e. ::main) is used as the main program. In fact, some threading libraries' thread classes have a method named main that the library user overrides with the code they want run in the thread.

Now, assuming you're not doing any namespace tricks, if you try to define ::main in two different .cpp files, the files themselves will both compile, however, the linker will abort since there are two definitions named main; it can't tell which to link.

(A question I have for the gurus out there: in C++, do the function definitions int main() {} and extern "C" int main() {} generate functions with the same signature? I haven't tried it myself.)

And now for the time you can have more than one ::main in your program's source: if one main is in a library (.a or .so file), and another is in your source (.o) files, the one in your sources wins and the one in the library is dropped, and linking succeeds unless there's some other problem! If you didn't write a main, the library's main would win. This is actually done in the support libraries that ship with lex and yacc; they provide a barebones main so you don't have to write one for a quick parser.

Which leads to an interesting application: providing a main with every library. My libraries tend to be small and focused, and so I put a main.cpp in every one with a main that is test or utility code for the library. For example, my shared memory library has a main that allows all the functions for managing shared memory to be called from the command line. Then I can test a variety of cases with a bash script. Anything that links in the shared memory library gets the test code for free, or can dispose of it simply by defining their own main.

EDIT: Just to make sure folks are clear on the concept, I'm talking about a build that looks like:

gcc -c -o bar_main.o bar_main.cpp
ar -r libbar.a bar_main.o
ranlib libbar.a
gcc -c -o foo_main.o foo_main.cpp
gcc -o foo foo_main.o -L. -lbar

In this example, the main in foo_main.o beats the main in bar_main.o. The standard doesn't define this behavior because they don't care. There's a lot of nonstandard things that people use anyway; Linux is an example with its use of C bitfields. ld has worked this way longer than I've known how to type.

Seriously, guys, feel free to strictly adhere to standards if you need to turn out least-common-denominator code. But if you have the luxury of working on a platform that can build lex and yacc programs, by all means, consider taking advantage of it.


there is only one entry point in the global scope.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号