stringtranslate.com

declaración anticipada

En programación de computadoras , una declaración directa es una declaración de un identificador (que denota una entidad como un tipo, una variable, una constante o una función) para la cual el programador aún no ha dado una definición completa .

Es necesario que un compilador conozca ciertas propiedades de un identificador (tamaño para la asignación de memoria , tipo de datos para la verificación de tipos, como la firma del tipo de funciones), pero no otros detalles, como el valor particular que contiene (en el caso de variables o constantes) o definición (en el caso de funciones). Esto es particularmente útil para compiladores de una sola pasada y compilaciones separadas.

La declaración directa se utiliza en idiomas que requieren una declaración antes de su uso; es necesario para la recursividad mutua en dichos lenguajes, ya que es imposible definir tales funciones (o estructuras de datos) sin una referencia directa en una definición: una de las funciones (respectivamente, estructuras de datos) debe definirse primero. También es útil permitir una organización flexible del código, por ejemplo si se desea colocar el cuerpo principal en la parte superior y las funciones llamadas debajo.

En otros idiomas, las declaraciones directas no son necesarias, lo que generalmente requiere un compilador de múltiples pasadas y que parte de la compilación se difiera hasta el tiempo de enlace . En estos casos, se deben definir identificadores (variables inicializadas, funciones definidas) antes de que puedan usarse durante el tiempo de ejecución sin necesidad de una predefinición en el código fuente para compilación o interpretación: no es necesario resolver inmediatamente los identificadores en una entidad existente. .

Ejemplos

Un ejemplo básico en C es:

void imprimirEsteInteger ( int ); 

En C y C++ , la línea anterior representa una declaración directa de una función y es el prototipo de la función . Después de procesar esta declaración, el compilador permitiría que el código del programa hiciera referencia a la entidad printThisIntegeren el resto del programa. La definición de una función debe proporcionarse en algún lugar (el mismo archivo u otro, donde sería responsabilidad del vinculador hacer coincidir correctamente las referencias a una función particular en uno o varios archivos objeto con la definición, que debe ser única, en otro) :

void printThisInteger ( int x ) { printf ( "%d \n " , x ); }     

Las variables pueden tener solo declaración directa y carecer de definición. Durante el tiempo de compilación, estos se inicializan mediante reglas específicas del lenguaje (a valores indefinidos, 0, punteros NULL, ...). Las variables que se definen en otros archivos fuente/objeto deben tener una declaración directa especificada con una palabra clave extern:

intfoo ;//foo podría estar definido en algún lugar de este archivo extern int bar ; //la barra debe estar definida en algún otro archivo     

En Pascal y otros lenguajes de programación de Wirth , es una regla general que todas las entidades deben declararse antes de su uso y, por lo tanto, la declaración directa es necesaria para la recursividad mutua, por ejemplo. En C, se aplica la misma regla general, pero con una excepción para funciones no declaradas y tipos incompletos. Por lo tanto, en C es posible (aunque imprudente) implementar un par de funciones mutuamente recursivas de la siguiente manera:

int primero ( int x ) { si ( x == 0 ) devuelve 1 ; de lo contrario, devuelve el segundo ( x -1 ); // reenviar referencia al segundo }             int segundo ( int x ) { si ( x == 0 ) devuelve 0 ; de lo contrario, regresa primero ( x -1 ); // referencia hacia atrás al primero }             

En Pascal, la misma implementación requiere una declaración directa de secondpara preceder su uso en first. Sin la declaración directa, el compilador generará un mensaje de error indicando que el identificador second se ha utilizado sin haber sido declarado.

Clases

En algunos lenguajes orientados a objetos como C++ y Objective-C , a veces es necesario declarar clases hacia adelante. Esto se hace en situaciones en las que es necesario saber que el nombre de la clase es un tipo, pero donde no es necesario conocer la estructura.

En C++, las clases y estructuras se pueden declarar de esta manera:

clase MiClase ; estructura MiEstructura ;  

En C++, las clases se pueden declarar hacia adelante si solo necesita usar el tipo de puntero a esa clase (ya que todos los punteros de objetos son del mismo tamaño, y esto es lo que le importa al compilador). Esto es especialmente útil dentro de definiciones de clases, por ejemplo, si una clase contiene un miembro que es un puntero (o una referencia) a otra clase.

La declaración directa se utiliza para evitar acoplamientos innecesarios, lo que ayuda a reducir el tiempo de compilación al reducir la cantidad de inclusión de encabezados. Esto tiene una triple ventaja:

La declaración directa de una clase no es suficiente si necesita usar el tipo de clase real, por ejemplo, si tiene un miembro cuyo tipo es esa clase directamente (no un puntero), o si necesita usarlo como clase base, o si necesitas utilizar los métodos de la clase en un método.

En Objective-C, las clases y protocolos se pueden declarar de esta manera:

@class  MiClase ; @protocol  Mi protocolo ;

En Objective-C, las clases y protocolos se pueden declarar hacia adelante si solo necesita usarlos como parte de un tipo de puntero de objeto, por ejemplo, MyClass * o id<MyProtocol> . Esto es especialmente útil dentro de definiciones de clases, por ejemplo, si una clase contiene un miembro que es un puntero a otra clase; Para evitar referencias circulares (es decir, esa clase también podría contener un miembro que sea un puntero a esta clase), simplemente declaramos las clases hacia adelante.

La declaración directa de una clase o protocolo no es suficiente si necesita subclasificar esa clase o implementar ese protocolo.

Referencia hacia adelante

El término referencia directa se utiliza a veces como sinónimo de declaración anticipada . [1] Sin embargo, más a menudo se entiende que se refiere al uso real de una entidad antes de cualquier declaración; es decir, la primera referencia seconden el código anterior es una referencia directa. [2] [3] Por lo tanto, podemos decir que debido a que las declaraciones directas son obligatorias en Pascal, las referencias directas están prohibidas.

Un ejemplo de referencia directa (válida) en C++ :

clase C { público : mutador vacío ( int x ) { myValue = x ; } int descriptor de acceso () const { return myValue ; } privado : int miValor ; };                   

En este ejemplo, hay dos referencias myValueantes de que se declare. C++ generalmente prohíbe las referencias directas, pero están permitidas en el caso especial de los miembros de la clase. Dado que la función miembro accessorno se puede compilar hasta que el compilador conozca el tipo de variable miembro myValue , es responsabilidad del compilador recordar la definición de accessorhasta que vea myValuela declaración.

Permitir referencias directas puede aumentar en gran medida la complejidad y los requisitos de memoria de un compilador y, en general, evita que el compilador se implemente en una sola pasada .

Referencias

  1. ^ MSDN: conversión a un tipo de clase de referencia directa
  2. ^ http://pages.cs.wisc.edu/~fischer/cs536.s07/lectures/Lecture25.4up.pdf [ URL básica PDF ]
  3. ^ Pensando en C++: Inlines y el compilador