2010-08-13 27 views
13

Esta pregunta es solo medio irónica. A veces sueño con un mundo sin matrices desnudas o cuerdas c.¿Por qué no se define main `main (std :: vector <std::string> args)`?

Si estás usando C++, no se debe a la definición preferida del principal ser algo como:

int main(std::vector<std::string> args) 

?

Ya hay varias definiciones de main para elegir, ¿por qué no hay una versión que tenga el espíritu de C++?

+3

Las implementaciones son libres de ofrecer otras firmas para main siempre que todas devuelvan un int. Entonces, una mejor pregunta sería ¿por qué no? –

Respuesta

4

Una preocupación que sigue volviendo a mi mente es que una vez que permite tipos complejos, termina con el riesgo de que se generen excepciones en el constructor del tipo. Y, como el lenguaje está diseñado actualmente, no hay forma de que se capture una excepción.Si se decidiera que tales excepciones deberían ser detectadas, entonces eso requeriría mucho más trabajo, tanto para el comité como para los escritores del compilador, lo que hace que todo sea un poco más problemático que simplemente decir "permitir std::vector<std::string>>".

Puede haber otros problemas también. El conjunto de "incompatibles con los tiempos de ejecución" me parece una especie de arenque rojo, dado que ahora puede proporcionar básicamente la misma funcionalidad con macros. Pero algo así es bastante más complicado.

+0

Última respuesta, pero creo que es la mejor. El problema real no es la compatibilidad con c o includes; es la posibilidad de excepciones. – Inverse

+0

Básicamente, no existe una posibilidad más de que se genere una excepción mediante una construcción std :: vector que mediante la construcción de una matriz de apuntadores de cadena y las cadenas terminadas en nulo a las que apuntan. – einpoklum

5

Porque le obligará a incluir <vector> y <string>.

+2

Además, le obligará a usar la misma implementación de '' y '' como la biblioteca de tiempo de ejecución. –

+0

@Mike: Pero no es necesario que ingrese 'main' desde la biblioteca de tiempo de ejecución. Si el compilador generó una función secreta que la biblioteca de tiempo de ejecución encontraría convertida de los argumentos C a los tipos C++ de su elección y luego llamó al 'principal 'real, no debería haber un conflicto. A menos que me esté perdiendo algo, sería un cambio completamente transparente. –

+2

Sin embargo, ya tiene la opción de al menos 2 variantes de 'main()'. Agregar un específico de C++ no necesariamente significa que se lo forzará a usarlo (las opciones existentes podrían permanecer como opciones). Esto bien podría complicar la maquinaria que el compilador/enlazador necesitaría para apoyar llamar correctamente a la 'main()' correcta, pero no es imposible. No estoy diciendo que necesariamente valdría la pena el costo y las complicaciones, solo que no es imposible. –

2

Básicamente, para seguir siendo compatible con C. Si tuviéramos que renunciar a eso, main() se movería a una clase.

+16

¿Por qué en la Tierra moverías principal a una clase? Eso ni siquiera tiene sentido. Java y C# solo lo hacen porque el lenguaje no permite las funciones no miembro, pero eso no lo convierte en un diseño menos terrible. decisión – jalf

11

Porque C++ fue diseñado para ser (casi) retrocompatible con el código C.

Existen casos en los que el código C se descompone en un compilador de C++, pero son bastante raros, y generalmente hay una buena razón por la cual se requiere esta rotura.

Pero cambiar la firma de la fuente principal, aunque es conveniente para nosotros, no es necesario. Para alguien portar código desde C, sería otra cosa que tenía que cambiar, sin obtener ningún beneficio en particular.

Otra razón es que std::vector es una biblioteca, no una parte del lenguaje central. Y entonces, tendría que #include <vector> en cada programa C++.

Y por supuesto, en sus primeros años, C++ no tiene un vector. Entonces, cuando el vector fue agregado al lenguaje, seguro, podría haber cambiado la firma de main, pero luego romperían no solo el código C, sino también todos los programas C++ existentes.

¿Vale la pena?

+3

Ya tenemos varias definiciones de 'main' para elegir, ¿por qué no agregar una versión en C++ ish? – Inverse

+6

Es cierto, eso podría hacerse. Pero, ¿realmente vale la pena la molestia? Puede simplemente hacer la primera línea de su programa 'std :: vector args (argv, argv + argc)'. El comité estándar solo prefiere agregar cosas nuevas al lenguaje si ofrece ventajas * significativas * sobre un enfoque de biblioteca. – jalf

+0

¿Es porque compilar STL en sí mismo? requeriría el soporte biblioteca ard que a su vez se llama principal? – Chubsdad

3

Porque C++ existía mucho antes que el estándar de C++, y se basaba mucho en C. Y, al igual que el estándar ANSI C original, codificar la práctica existente era una parte importante del mismo.

No tiene sentido cambiar algo que funciona, especialmente si se rompe un montón de código existente.

Incluso ISO C, que ha pasado por bastantes iteraciones, todavía toma compatibilidad hacia atrás muy muy en serio.

1

Trataré de explicar en la mejor frase posible.

C++ fue diseñado para ser compatible con C y std::vector se incluyó en una biblioteca que solo se incluyó en C++.

Además, los programas C++ y C se diseñaron para ejecutarse en shells o líneas de comando (windows, linux, mac) y OS pasan argumentos a un programa como una matriz de String. ¿Cómo un sistema operativo realmente traduciría vectores?

Esa es la razón más importante que se me ocurre, no dude en criticarlo.

4

Como @jalf, a veces me encuentro escribiendo

int main(int argc, char** argv) { 
    std::vector<std::string> args(argv, argv+argc); 

Pero sí, como todo el mundo dice, main tiene que ser compatible C. Lo veo como una interfaz para el tiempo de ejecución del sistema operativo, que es (al menos int los sistemas que uso) está escrito en C.

Aunque algunos entornos de desarrollo fomentan reemplazos como wmain o _tmain. Puede escribir su propio compilador/IDE, lo que fomentaría el uso de int vmain(const std::vector<std::string>& args).

+1

El tiempo de ejecución ya tiene que saber algo sobre C++, para crear y destruir objetos estáticos y manejar excepciones no detectadas. Por lo tanto, no sería un gran salto permitir variantes específicas de C++ de 'main'; la única objeción real a esto es que tendrías que estandarizar la implementación de 'vector' y' string'. –

+0

@Mike Seymour: supongo que tienes razón ... Y entonces surge la pregunta de por qué exactamente std :: basic_string y por qué exactamente std :: vector. Yo votaría por 'int main (std :: initializer_list >)'! – Cubbi

+1

Para llevar esto un paso más allá, solo tiene un fragmento 'main()' que puede tener como plantilla inicial en su editor/IDE que no hace más que 'return cppMain (vector (argv, argv + argc));' y use 'cppMain()' como punto de inicio 'personalizable' de su programa. De hecho, puedo comenzar a usar esto ... –

9

Hay otra razón además de la compatibilidad con C. En C++, , la biblioteca estándar está destinada a ser totalmente opcional. No hay nada sobre el lenguaje C++ en sí que lo obligue a usar elementos de la biblioteca estándar como std::string y std::vector, y eso es totalmente por diseño. De hecho, es por diseño que debería poder usar algunas partes de la biblioteca estándar sin tener que usar otras (aunque esto ha llevado a algunas cosas generalmente molestas como std::ifstream y std::ofstream que operan en cadenas de estilo C const char* en lugar de std::string objetos).

La teoría es que se supone que usted puede tomar el lenguaje C++ y usar cualquier biblioteca de objetos, contenedores, etc. que desee, ya sea la biblioteca estándar o alguna biblioteca propietaria (por ejemplo, Qt, MFC), o algo que tú mismo creaste. Definir main para aceptar un argumento compuesto por tipos definidos en la biblioteca estándar derrota este objetivo de diseño.

+1

Excepto que todavía hay cosas como std :: type_info que son utilizadas por características que no son std :: language. –

+0

Pero OP preguntaba por una _opción_ para tener 'main()' definido de esta manera. Si esto fuera posible, aún podría tener su estilo C 'main()' y ninguna biblioteca estándar. – einpoklum

2

Las definiciones múltiples de main() no son realmente definiciones múltiples. Hay tres:

  • int main(void) (C99)
  • int main(int argc, char *argv[]) (C99)
  • int main(int argc, char *argv[], char *envp[]) (POSIX, creo)

Pero en POSIX, sólo realmente obtener la tercera. El hecho de que se puede llamar a una función con argumentos adicionales se debe a la convención de llamadas de C.

can not tienen extern "C" int main(std::vector<std::string> argv) a menos que el diseño de memoria sea mágicamente compatible de forma portátil. El tiempo de ejecución llamará a main() con los argumentos incorrectos y fallará. No hay una forma fácil de evitar esto.

lugar de ello, proporcionan main() noextern "C" era, el tiempo de ejecución podrían tratar los diversos símbolos soportados en orden hasta que encuentra uno. Imagino que main() es extern "C" de forma predeterminada y que no se pueden sobrecargar las funciones extern "C".

Para más diversión, void main(void).

+1

Olvidó el – Inverse

+0

del 'wmain' Eso parece ser una característica de VC++. No es obvio cómo se implementa (¿se vincula a un tiempo de ejecución diferente, tal vez?). –