Две основные функции - PullRequest
6 голосов
/ 13 апреля 2010

Можем ли мы иметь две main() функции в программе на C ++?

Ответы [ 8 ]

19 голосов
/ 13 апреля 2010

Стандарт прямо говорит в 3.6.1:

Программа должна содержать глобальную функцию main, которая является назначенным началом программы. [...] Эта функция не должна быть перегружена.

Таким образом, в глобальной области видимости может быть только одна main функция. На функции в других областях, которые также называются main, это не влияет, их может быть любое количество.

11 голосов
/ 13 апреля 2010

Только одна функция может быть названа main вне любого пространства имен, как и для любого другого имени. Если у вас есть пространства имен foo и bar (и т. Д.), У вас вполне могут быть функции с именами foo::main, bar::main и т. Д., Но они не будут рассматриваться как нечто особенное с точки зрения системы только функция с именем main вне какого-либо пространства имен рассматривается как точка входа в программу). Конечно, из вашего main вы могли бы прекрасно назвать различные foo::main, bar::main и т. Д.

8 голосов
/ 13 апреля 2010

Да! Почему нет?

Рассмотрим следующий код:

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

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

Это ::main(), которое будет вызываться во время выполнения.

4 голосов
/ 13 апреля 2010

Вы не можете перегрузить main () в глобальной области видимости.

3 голосов
/ 13 апреля 2010

Программа может иметь только одну точку входа, но, конечно, одна функция 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' и т. д.

2 голосов
/ 13 апреля 2010

В одной программе допускается только одна точка входа.

1 голос
/ 13 апреля 2010

Ох, вопрос с подвохом!

Краткий ответ: "Это зависит".

Длинный ответ: Как уже отмечали другие, вы можете иметь несколько функций с именем main, если онинаходятся в разных пространствах имен, и в качестве основной программы используется только main в корневом пространстве имен (т.е. ::main).На самом деле, классы потоков некоторых потоковых библиотек имеют метод с именем main, который пользователь библиотеки переопределяет с помощью кода, который он хочет запустить в потоке.

Теперь, если вы не делаете никаких трюков с пространством имен, есливы пытаетесь определить ::main в двух разных .cpp файлах, оба файла сами будут скомпилированы, однако компоновщик прервется, поскольку есть два определения с именем main;он не может сказать, на какую ссылку связать.

(У меня есть вопрос к гуру: в C ++ определения функций int main() {} и extern "C" int main() {} генерируют функции с одинаковой сигнатурой? У меня нет 'Я сам не пробовал.)

А теперь на время у вас может быть более одного ::main в источнике вашей программы : если один main находится в библиотеке (.a или.so файл), а другой находится в ваших исходных (.o) файлах, тот, что в ваших источниках, побеждает, а тот, что в библиотеке, удаляется, , и связывание успешно , если нет какой-либо другой проблемы!Если бы вы не написали 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 в foo_main.o превосходит main в bar_main.o.Стандарт не определяет это поведение, потому что им все равно.Есть много нестандартных вещей, которыми люди все равно пользуются;Linux является примером использования битовых полей Си.ld работал таким образом дольше, чем я знал, как печатать.

Серьезно, ребята, не стесняйтесь строго придерживаться стандартов, если вам нужен код наименьшего общего знаменателя.Но если у вас есть возможность работать на платформе, которая может создавать программы lex и yacc, во что бы то ни стало, рассмотрите возможность воспользоваться этим.

0 голосов
/ 13 апреля 2010

в глобальной области видимости есть только одна точка входа.

...