Да! Вы можете покончить с главным.
Отказ от ответственности: Вы спрашивали, возможно ли это, а не если это нужно сделать. Это абсолютно не поддерживаемая, плохая идея. Я сделал это сам по причинам, в которые я не попаду, но я не рекомендую это. Моя цель не избавилась от основной, но она тоже может это сделать.
основных шагов заключаются в следующий:
- Найти
crt0.c
в исходном каталоге CRT вашего компилятора.
- Добавить
crt0.c
в свой проект (копия, а не оригинал).
- Найти и удалить звонок на главную из
crt0.c
.
Получение его для компиляции и ссылки может быть затруднено; Насколько сложно зависит от того, какой компилятор и какая версия компилятора.
Добавлено
Я просто сделал это с Visual Studio 2008, так вот точные шаги, которые вы должны предпринять, чтобы заставить его работать с этим компилятором.
- Создайте новое консольное приложение C++ Win32 (нажмите кнопку Далее и отметьте
Empty Project
).
- Добавить новый элемент .. Файл C++, но назовите его
crt0.c
(не .cpp).
- Скопируйте содержимое
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\crt\src\crt0.c
и вставьте в crt0.c
.
- Найти
mainret = _tmain(__argc, _targv, _tenviron);
и прокомментировать.
- Щелкните правой кнопкой мыши на
crt0.c
и выберите Свойства.
- Set C/C++ -> Общие сведения -> Дополнительные каталоги включений =
"C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\crt\src"
.
- Set C/C++ -> Препроцессор -> Определения препроцессора =
_CRTBLD
.
- Нажмите OK.
- Щелкните правой кнопкой мыши название проекта и выберите «Свойства».
- Set C/C++ -> Генерация кода -> Библиотека времени выполнения =
Multi-threaded Debug (/MTd)
(*).
- Нажмите OK.
- Добавить новый элемент .. Файл C++, назовите его как угодно (
app.cpp
для этого примера).
- Вставьте код ниже в
app.cpp
и запустите его.
(*) Вы не можете использовать DLL времени выполнения, вам необходимо статически ссылаться на библиотеку времени выполнения.
#include <iostream>
class App
{
public: App()
{
std::cout << "Hello, World! I have no main!" << std::endl;
}
};
static App theApp;
Добавлено
Я удалил superflous вызов выхода и аннотацию о жизни, как я думаю, мы все способны понять последствия удаления основной.
Ультра Necro
Я просто наткнулся на этот ответ и читать как это и возражения Джона Dibling в ниже. Было очевидно, что я не объяснил, что делает вышеуказанная процедура, и почему это действительно удаляет основной из программы целиком.
Джон утверждает, что «в CRT всегда есть главная». Эти слова не совсем правильны, но дух утверждения есть. Main не является функцией, предоставляемой CRT, вы должны добавить ее самостоятельно. Вызов этой функции содержится в функции точки входа CRT.
Точка входа каждой программы C/C++ является функцией в модуле с именем crt0. Я не уверен, что это соглашение или часть спецификации языка, но каждый компилятор C/C++, с которым я столкнулся (что очень много), использует его.Эта функция в основном делает три вещи:
- Инициализировать CRT
- Позвонить в
- Сорвите
В приведенном выше примере, вызов _tmain, но это какой-то макрос магии, чтобы позволить различные формы, которые «основные» могут иметь, некоторые из которых являются VS специфическими в этом случае.
Что делает вышеприведенная процедура, так это удаление модуля crt0 из CRT и замена его на новый. Вот почему вы не можете использовать DLL Runtime, в этой DLL уже есть функция с тем же именем точки входа, что и добавляемое (2). Когда вы статически связываете, CRT представляет собой коллекцию .lib-файлов, а компоновщик позволяет полностью переопределять модули .lib. В этом случае модуль с только одной функцией.
Наша новая программа содержит запасной CRT, минус его модуль CRT0, но с модулем CRT0 нашего собственного создания. Там мы удаляем вызов на главный. Так что нет нигде!
(2) Возможно, вы могли бы использовать DLL runtime, переименовав функцию точки входа в файл crt0.c и изменив точку входа в настройках компоновщика. Однако компилятор не знает об изменении точки входа, и DLL содержит внешнюю ссылку на «главную» функцию, которую вы не предоставляете, поэтому она не будет компилироваться.
Интересный вопрос. Я никогда не думал, что у меня есть один глобальный объект. Как вы говорите, плохая практика, но тем не менее интересная. –
что-то подобное реализовано в MFC, где у вас есть один экземпляр 'CWinApp' – Andrey
@CwinApp, MFC предоставляет вам основную/winmain. Итак, у вас все еще есть функция main() в MFC. –