Мы можем иметь два main()
функции в программе C++?
Стандарт прямо говорит в 3.6.1:
Программа должна содержать глобальную функцию с именем 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' в это и т. д.
в глобальной области существует только одна точка входа.
Да! Почему бы и нет?
Рассмотрим следующий код:
namespace ps
{
int main(){return 0;}
}
int main()
{
ps::main();
}
Его :: main ()
, который будет вызываться во время выполнения.
Вы не можете перегрузить main () в глобальной области.
Только одна функция может иметь имя main
вне любого пространства имен, как и любое другое имя. Если у вас есть пространства имен foo
и bar
(и т.д.), вы вполне можете иметь функции с именами foo :: main
, bar :: main
и т. д., но они не будут рассматриваться как что-то особенное с точки зрения системы (только функция с именем main
вне любого пространства имен обрабатывается отдельно как точка входа в программу). Конечно, из вашего main
вы могли бы прекрасно вызывать различные foo :: main
, bar :: main
и так далее.
Ох, вопрос с подвохом!
Краткий ответ: «Это зависит».
Длинный ответ: как указывали другие, у вас может быть несколько функций с именем main
, если они находятся в разных пространствах имен, и только ] main
в корневом пространстве имен (т.е. :: main
) используется как основная программа. Фактически, классы потоков некоторых библиотек потоков имеют метод с именем main
, который пользователь библиотеки переопределяет кодом, который он хочет запустить в потоке.
Предполагая, что вы не делаете никаких трюков с пространством имен, если вы попытаетесь определить :: main
в двух разных файлах .cpp
, оба файла будут компилироваться, однако , компоновщик будет прерван, так как есть два определения с именем main
; он не может сказать, на что нужно ссылаться.
(У меня вопрос к гуру: в C ++ выполните определения функций int main () {}
и extern "C" int main () {}
генерировать функции с такой же сигнатурой? Я сам не пробовал.)
А теперь на время вы можете иметь более одного :: main
в исходном коде вашей программы : если один main
находится в библиотеке (файл .a или .so), а другой находится в ваших исходных (.o) файлах, то выигрывает тот, который находится в ваших источниках, а тот, который находится в библиотеке, удаляется, и связывание завершается успешно , если нет других проблем! Если бы вы не написали main
, библиотека main
выиграла бы. Фактически это делается в библиотеках поддержки, которые поставляются с lex
и yacc
; они предоставляют barebones 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
в foo_main.o
превосходит main
в bar_main.o
. Стандарт не определяет такое поведение, потому что им все равно. В любом случае люди используют множество нестандартных вещей; Linux является примером использования битовых полей C. ld
работает таким образом дольше, чем я умею печатать.
Серьезно, ребята, не стесняйтесь строго придерживаться стандартов, если вам нужно получить код с наименьшим общим знаменателем. Но если у вас есть возможность работать над платформой, которая может создавать программы lex
и yacc
, во что бы то ни стало, подумайте о том, чтобы воспользоваться этим.