我们可以main()
在 C++ 程序中有两个函数吗?
8 回答
该标准在 3.6.1 中明确指出:
一个程序应包含一个名为 main 的全局函数,它是程序的指定开始。[...]此功能不得重载。
所以在一个程序的全局范围内只能有一个main
函数。其他范围内也被调用main
的函数不受此影响,可以有任意数量。
main
与任何其他名称一样,只能在任何命名空间之外命名一个函数。如果你有命名空间foo
和bar
(等)你可以很好地拥有名为foo::main
,等的函数bar::main
,但从系统的角度来看,它们不会被视为任何特殊的东西(只有在main
任何命名空间之外命名的函数才会被特殊对待,作为程序的入口点)。当然,main
您可以完全调用各种foo::main
,bar::main
等。
是的!为什么不?
考虑以下代码:
namespace ps
{
int main(){return 0;}
}
int main()
{
ps::main();
}
它::main()
会在执行期间被调用。
您不能在全局范围内重载 main() 。
一个程序只能有一个入口点,但当然,一个 main() 函数可以调用其他函数,具体取决于您要指定的任何逻辑。因此,如果您正在寻找一种将两个或多个程序有效地编译为单个可执行文件的方法,您可以执行以下操作:
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;
}
...然后只需将您的“其他”main() 函数重命名为 frogger_main()、pacman_main() 或您愿意为其命名的任何名称,如果可执行文件名称中有单词,您将拥有一个作为 Frogger 运行的程序'frogger',或者如果可执行文件中包含名称'pacman',则作为 PacMan 运行,等等。
在一个程序中,只允许一个入口点。
哦,诡计问题!
简短的回答:“这取决于。”
长答案:正如其他人所指出的,main
只要它们位于不同的命名空间中,您就可以命名多个函数,并且只有main
根命名空间中的(即::main
)用作主程序。事实上,一些线程库的线程类有一个名为的方法main
,库用户使用他们希望在线程中运行的代码覆盖该方法。
现在,假设你没有做任何命名空间技巧,如果你尝试::main
在两个不同.cpp
的文件中定义,文件本身都会编译,但是,链接器将中止,因为有两个名为main
;的定义。它不知道要链接哪个。
(我对那里的大师有一个问题:在 C++ 中,执行函数定义int main() {}
并extern "C" int main() {}
生成具有相同签名的函数?我自己没有尝试过。)
现在,您的程序源代码中可以有多个::main
:如果一个main
在库(.a 或 .so 文件)中,另一个在您的源文件(.o)中,则源文件中的那个获胜并且库中的那个被删除,除非有其他问题,否则链接会成功!如果你不写 a main
,图书馆main
会赢。这实际上是在lex
和yacc
;附带的支持库中完成的。它们提供了准系统main
,因此您不必为快速解析器编写准系统。
这导致了一个有趣的应用程序:为main
每个库提供一个。我的库往往很小而且很集中,所以我main.cpp
在每个main
库中都放了一个测试或实用程序代码。例如,我的共享内存库有一个main
允许从命令行调用管理共享内存的所有函数。bash
然后我可以用一个脚本来测试各种案例。任何在共享内存库中链接的东西都可以免费获得测试代码,或者可以通过定义自己的main
.
编辑:为了确保人们清楚这个概念,我正在谈论一个看起来像这样的构建:
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
在此示例中,main
infoo_main.o
击败main
in bar_main.o
。该标准没有定义这种行为,因为他们不在乎。无论如何,人们都会使用很多非标准的东西。Linux 就是一个使用 C 位域的例子。 ld
以这种方式工作的时间比我知道如何打字的时间长。
说真的,伙计们,如果您需要生成最小公分母代码,请随意严格遵守标准。lex
但是,如果您有幸在一个可以构建和编程的平台上工作,那么一定yacc
要考虑利用它。
全局范围内只有一个入口点。