2010-06-24 11 views
5

lo que es la descripción o el significado de esto: por ejemplo:¿Cuál es el propósito de la declaración directa?

class test; 

class test 
{ 
    ..... 
}; 
+2

La próxima vez es posible que desee tener un título que en realidad es ** ** un título :) – ereOn

+4

Editado su pregunta a tener un título significativo. – Puppy

+0

Esto parece un duplicado de http://stackoverflow.com/questions/2632601/why-are-forward-declarations-necessary, que se cerró por ser un duplicado. – Ferruccio

Respuesta

4

En primer lugar, la clase es declarada , entonces es definido .

Declaración: Simplemente le dice al compilador: Ok, aquí hay algo (método, clase, etc.), que puede usarse con el nombre de pila. Simplemente vincula el nombre de pila a algo.

Definición: Le dice al compilador: Ok, esto es qué (y cómo) los métodos, clases, etc. realmente hacen sus cosas. Si se define algo, entonces el compilador se hace realmente asignar espacio para ello.

Puede echar un vistazo a here.

0

Ehm, la pregunta no es muy clara. Sin embargo, el código suministrado declara una clase test y la define a continuación, omitiendo los miembros reales (...).

1

La primera línea es lo que se denomina una declaración directa. Trae el nombre de la clase al espacio de nombre actual sin definirlo realmente.

0

La respuesta simple es que cuando utiliza el primer formulario, puede mantener punteros o referencias a una clase sin necesidad de la implementación completa. Esto puede ser muy útil cuando dos clases interactúan estrechamente y sus implementaciones o definiciones son difíciles de separar.

21

C++ (como C) fue diseñado para ser implementable por un compilador de un solo pase. Las referencias hacia delante son necesarias en los casos en que el compilador necesita saber que un símbolo se refiere a una clase antes de que la clase esté realmente definida. El ejemplo clásico de esto es cuando dos clases necesitan contener punteros entre sí. es decir

class B; 

class A { 
    B* b; 
}; 

class B { 
    A* a; 
}; 

Sin la referencia hacia adelante a B, el compilador no puede analizar correctamente la definición de A y usted no puede solucionar el problema poniendo la definición de B antes de A.

En un lenguaje como C#, que necesita un compilador de dos pasadas, no es necesario hacia adelante hace referencia a

class A { 
    B b; 
} 

class B { 
    A a; 
} 

porque en primer pase del compilador simplemente recoge todas las definiciones de los símbolos. Cuando el compilador realiza su segundo pase, puede decir "Sé que B es una clase porque vi la definición en mi primer pase".

+2

+1 para discutir referencias circulares. – Brian

+0

¿Cuántos pases usa 'gcc'? – Lazer

+0

@Lazer: No conozco los detalles para GCC, pero la mayoría de los compiladores modernos de C & C usan múltiples pases. Solo hacen una pasada sobre el código fuente real y lo convierten en algún tipo de representación interna. Luego hacen una o (generalmente) más pases de optimización sobre esta representación interna antes de que pase la generación de código. – Ferruccio

7

El compilador necesita la definición de una clase si se accede a los miembros/métodos de esa clase o si es necesario conocer el tamaño. En otros casos, una declaración directa es suficiente. Esto le ahorra tiempo de compilación. Ejemplo:

class A { 
    B m_b; 
    C* m_ptrC; 
}; 

Para esta clase, se necesita la definición de B (tamaño necesario) y sólo la declaración de C (punteros han fijado tamaño). Solo necesita incluir el encabezado de B, no el de C. Una declaración de avance de C es suficiente.

a.h:

#ifndef A_H 
#define A_H 

#include <b.h> 
class C; 

class A 
{ 
    B m_b; 
    C* m_ptrC; 
} 
#endif 

La declaración de avance de C (en lugar de incluir c.h que también es posible) le ahorra el análisis c.h siempre que incluya A. H. En un proyecto grande, esto puede ahorrar mucho tiempo de compilación. Otra ventaja es que los cambios en c.h no desencadenan una recompilación de a en este caso. No sé si el compilador lo reconoce si incluye c.h en lugar de anunciarlo.

Para obtener más información, intente comprender el pimpl-idioma (sólo Google para ello. Obtendrá un montón de éxitos).

Por supuesto, en a.cpp si realmente hace algo con el puntero hacia c (por ejemplo, m_ptrC-> Agregar()), deberá incluir c.h. Pero a.cpp se lee solo una vez, donde el archivo de encabezado se lee n veces con n grande para las clases que se usan con mucha frecuencia en proyectos grandes.

declaración adelantada también permite dependencias circulares. Ejemplo:

class B; 

class A { 
B* m_ptrB; 
} 

class B { 
A* m_ptrA; 
} 

Sólo recuerde - no se puede usar ninguna información sobre el tamaño & métodos si se utiliza hacia adelante declaraciones. Este es también el caso con 2 clases que se incluyen entre sí (una clase no necesita la referencia directa). Personalmente, creo que las referencias circulares son malas y, si es posible, debes evitarlas.

Para obtener información adicional: C++ FAQ

Gracias por el comentario acerca de las dependencias circulares, simplemente se olvidó de ellos.

+0

1 por mencionar la razón por la que uno quiere utilizar declaraciones hacia adelante ... – rubenvb

+0

El uso del compilador de eficiencia legítima, pero creo que el uso de referencia circular es un mejor punto de partida a la hora de pensar en el propósito de referencias hacia delante. – Brian

Cuestiones relacionadas