2010-02-07 18 views
8

En C es opcional. En C++ uno "DEBE" declarar una función antes de su uso/definición. ¿Por que es esto entonces? ¿Cuál es la necesidad? No hacemos eso en C# o Java.¿Por qué una función necesita ser declarada antes de ser definida o utilizada?

Lo curioso es que estamos definiendo una función. La definición en sí tiene una declaración incluso entonces, tenemos que declarar. Dios sabe por qué?

+1

Según sus preguntas, supongo que no le gusta mucho C++. –

+0

En realidad, estaba enamorado de C/C++. Luego aprendí Java, me sentí bien. Ahora, estoy haciendo C#. Me encanta, pero ahora comencé a encontrar fallas en C/C++. :( – norris

+3

No debemos olvidar que esta restricción se elimina en C++ para las llamadas a funciones miembro dentro de las clases 'struct A {void f() {g();/* before declarated! * /} Void g() {}}; ' –

Respuesta

22

Es curioso que usted menciona que, esta misma semana Eric Lippert escribió una publicación relacionada con su pregunta:

http://blogs.msdn.com/ericlippert/archive/2010/02/04/how-many-passes.aspx

Básicamente, esto se relaciona con cómo funciona el compilador. Los compiladores C# y Java realizan varias pasadas. Si encuentran una llamada a un método que aún no se conoce, eso no es un error, porque la definición se puede encontrar más adelante y la llamada se resolverá en el próximo pase. Tenga en cuenta que mi explicación es demasiado simplista, sugiero que lea la publicación de Eric Lippert para obtener una respuesta más completa ...

8

Java y C# especifican el idioma y el formato de archivo de objeto binario, y son compiladores de múltiples pasos.

Como resultado, pueden ver las definiciones posteriores o las que se compilaron por separado.

C no funciona de esta manera por varias razones:

  • Sin utilizar el código administrado que es mucho más difícil de definir un formato de objeto independiente de la máquina con la información de tipo

  • C permite deliberadamente pasando por alto los mecanismos de tipo

  • Cuando se definió originalmente, generalmente no había suficiente memoria para ejecutar compiladores sofisticados, ni hubo prototipos para leer de todos modos

  • Los programas C deben ser arbitrariamente grandes con los mecanismos de ruta de búsqueda y biblioteca específicos del sistema. Todo esto se interpone en el camino de la definición de un sistema de tipo de objeto de base módulo

  • Parte de la base de portabilidad e interoperabilidad C es el "idioma de entrada única" naturaleza de la especificación

  • Hasta hace poco, incluso la naturaleza limitada de una sola pasada de C era apenas práctica para programas grandes. Algo así como Java o C# hubiera estado fuera de la pregunta: ¿se puede tomar unas vacaciones y su make(1) continuarían sin hacer

+1

El último punto en realidad es una debilidad de 'make (1)' , no tanto C. Es bastante genérico y poderoso, pero a un precio muy alto: 'make' no entiende una sola cosa. Una herramienta más especializada puede ser mucho, mucho más efectiva en la construcción de C entendiendo la conceptos básicos de CEg 'make' simplemente no grok encabezados – MSalters

5

Básicamente, hay que bajar a la forma de escribir el compilador para el lenguaje. En C++, la decisión ha sido hacer posible una compilación de una sola pasada. Para hacer eso, usted (o más bien el compilador) necesita poder leer primero la declaración de todas las clases, métodos y similares y luego leer la implementación (o en términos de C++, la definición). En Java y C#, el compilador lee primero todo el código que genera lo que corresponde a lo que el compilador de C++ genera al leer los archivos de encabezado. El compilador C#/Java lee la implementación (definición aka). Entonces, en C++, se le pide al desarrollador que escriba la declaración, mientras que en C#, el compilador ejecuta el código varias veces haciendo el trabajo de declaración para el desarrollador.

Como nota aparte, otros idiomas solían pedirle que escribiera las funciones en el orden en que las necesitaba (si la función B usa la función A, primero debe definir A). La mayoría de esos idiomas tenían construcciones para permitirte evitar esto. En (Turbo) Pascal, la solución era, en un tipo, la misma que en C++.

-3

En C++ un "MUST" declara una función antes de su uso/definición. ¿Por que es esto entonces? ¿Cuál es la necesidad? No hacemos eso en C# o Java.

Me gustaría decir que eso no es cierto. Sí, en C++ debe definir una firma de función (prototipo) antes de referirse a ella. Pero puede dejar la implementación para un momento posterior.

En Java eso no funciona: no se puede llamar al método de alguna clase sin tener esa clase compilada (nota: junto con la implementación) y disponible en el classpath de javac. Entonces, Java es más estricto en este sentido.

+0

No lo hice -1 porque creo que -2 es suficiente. Sin embargo, ¿has oído hablar de interfaces? En OOP están lo más cerca posible de los prototipos de función que puede obtener. – Fredrik

+0

La parte sobre Java simplemente no es verdad. La especificación de Java dice: "Los tipos declarados en diferentes unidades de compilación pueden depender el uno del otro, circularmente. Un compilador Java debe organizar compilar todos esos tipos al mismo tiempo" (7.3) – Niki

+0

La parte sobre C++ tampoco es verdadera. El tipo en la pregunta es correcto. –

2

C++ contra Java/C# - compilador de un solo paso (C++) frente a compilador de múltiples pasadas (Java & C#). Múltiples pasadas permiten a los compiladores de Java y C# echar un vistazo a prototipos de tipos y funciones futuros.

C++ contra C - La característica C para tener una declaración predeterminada es básicamente un error, corregido en C++. Causa problemas, y es una advertencia habilitada para gcc. En C++, los argumentos forman parte de la función exported name (name-mangling), por lo que deben conocerse antes de poder llamar a la función correcta.

Cuestiones relacionadas