Sí! Puede deshacerse de main.
Descargo de responsabilidad: Ha preguntado si era posible, no si debería hacerse. Esta es una mala idea totalmente sin respaldo. Lo hice yo mismo, por razones que no abordaré, pero no lo estoy recomendando. Mi propósito no era deshacerme de main, pero también puede hacerlo.
Los pasos básicos son los siguientes:
- Encuentra
crt0.c
en el directorio fuente CRT de su compilador.
- Agregue
crt0.c
a su proyecto (una copia, no el original).
- Encuentra y elimina la llamada al principal desde
crt0.c
.
Hacer que compilar y vincular puede ser difícil; Qué difícil depende de qué compilador y qué versión del compilador.
Agregado
sólo lo hice con Visual Studio 2008, así que aquí están los pasos exactos que hay que tomar para conseguir que funcione con ese compilador.
- Cree una nueva aplicación de consola C++ Win32 (haga clic en siguiente y marque
Empty Project
).
- Agregar nuevo elemento ... Archivo C++, pero nómbrelo
crt0.c
(no .cpp).
- Copie los contenidos de
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\crt\src\crt0.c
y péguelos en crt0.c
.
- Encuentra
mainret = _tmain(__argc, _targv, _tenviron);
y coméntalo.
- Haga clic derecho en
crt0.c
y seleccione Propiedades.
- Establecer C/C++ -> General -> Directorios de inclusión adicionales =
"C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\crt\src"
.
- Establecer C/C++ -> Preprocesador -> Definiciones de preprocesador =
_CRTBLD
.
- Haga clic en Aceptar.
- Haga clic con el botón derecho en el nombre del proyecto y seleccione Propiedades.
- Establecer C/C++ -> Generación de código -> Biblioteca de tiempo de ejecución =
Multi-threaded Debug (/MTd)
(*).
- Haga clic en Aceptar.
- Agregar nuevo elemento ... Archivo C++, asígnele el nombre (
app.cpp
para este ejemplo).
- Pegue el siguiente código en
app.cpp
y ejecútelo.
(*) No puede usar la DLL de tiempo de ejecución, tiene que enlazar estáticamente a la biblioteca de tiempo de ejecución.
#include <iostream>
class App
{
public: App()
{
std::cout << "Hello, World! I have no main!" << std::endl;
}
};
static App theApp;
Agregado
que eliminan la llamada de salida superfluo y la propaganda sobre la vida, ya que creo que todos somos capaces de entender las consecuencias de la eliminación principal.
Ultra Necro
me encontré con esta respuesta y leer tanto ella como las objeciones de John Dibling abajo. Resultó evidente que no expliqué lo que hace el procedimiento anterior y por qué eso elimina el programa principal del programa por completo.
John afirma que "siempre hay un problema principal" en el CRT. Esas palabras no son estrictamente correctas, pero el espíritu de la declaración sí lo es. Main no es una función proporcionada por el CRT, debe agregarlo usted mismo. La llamada a esa función está en la función de punto de entrada proporcionada por CRT.
El punto de entrada de cada programa C/C++ es una función en un módulo llamado 'crt0'. No estoy seguro de si esto es una convención o parte de la especificación del lenguaje, pero cada compilador C/C++ que he encontrado (que es mucho) lo usa.Esta función hace básicamente tres cosas:
- inicializar el CRT
- Call principal
- derribar
En el ejemplo anterior, se _tmain la llamada, pero eso es un poco de magia macro para permitir las diversas formas que puede tener 'principal', algunas de las cuales son VS específicas en este caso.
Lo que hace el procedimiento anterior es que elimina el módulo 'crt0' del CRT y lo reemplaza por uno nuevo. Esta es la razón por la que no puede usar la DLL de Runtime, ya existe una función en esa DLL con el mismo nombre de punto de entrada que la que estamos agregando (2). Cuando vincula estáticamente, el CRT es una colección de archivos .lib, y el enlazador le permite anular por completo los módulos .lib. En este caso, un módulo con una sola función.
Nuestro nuevo programa contiene el stock CRT, menos su módulo CRT0, pero con un módulo CRT0 de nuestra propia creación. Ahí eliminamos la llamada a main. ¡Así que no hay main en ninguna parte!
(2) Puede pensar que podría utilizar el DLL de tiempo de ejecución al cambiar el nombre de la función de punto de entrada en su archivo crt0.c y cambiar el punto de entrada en la configuración del enlazador. Sin embargo, el compilador desconoce el cambio del punto de entrada y el archivo DLL contiene una referencia externa a una función 'principal' que no está proporcionando, por lo que no compilaría.
Interesante pregunta. Nunca consideré tener un solo objeto global. Como dices, mala práctica pero interesante de todos modos. –
algo así se implementa en MFC donde tiene instancia única de 'CWinApp' – Andrey
@CwinApp, MFC proporciona main/winmain para usted. Por lo tanto, todavía tiene una función main() en MFC. –