2010-02-04 24 views
7

puedo hacer estoPor qué no puedo realizar varias declarar una clase

extern int i; 
extern int i; 

Pero no puedo hacer lo mismo con una clase

class A { 
.. 
} 
class A { 
.. 
} 

Mientras que en ambos casos no hay memoria siendo asignado.

+0

¿Se supone que son dos clases diferenciadas? o una clase parcial? – Naveen

+0

@all En realidad, mi entendimiento es que el hecho diferenciador entre una definición y una declaración es - no se asigna memoria en este último. Es por eso que consideré que la clase A {..} era más una declaración que una definición. – deeJ

Respuesta

25

Los siguientes son declaraciones:

extern int i; 
class A; 

y los dos siguientes son definiciones:

int i; 
class A { ... } 

Las reglas son:

  • una definición es también una declaración .
  • tiene que haber 'visto' una declaración de un artículo antes de poder usarlo.
  • la nueva declaración es correcta (debe ser idéntica).
  • la redefinición es un error (la regla de una definición).
+0

Lo dijiste mejor. Retiro mi respuesta –

+3

Por lo que vale, esto se llama Regla de una sola definición. – GManNickG

+6

Puede agregar que "clase A"; Es, de hecho, la declaración de la clase A. – Klaim

2

La primera (extern) hace referencia a una variable existente. Entonces solo indica la variable dos veces.

La declaración de clase da sentido a un tipo (su clase: A). Está tratando de darle dos significados a A. Esto no le sirve de nada, y solo puede confundir, por lo que el compilador lo protege de él.

Por cierto, si coloca ambas clases en espacios de nombres de diferencia, puede asignarles el mismo nombre.

0

Pero en el primer caso no hay contradicción.

extern int i; 
extern double i; 

tampoco funcionará. Así que si creas la clase A a veces no sería posible decidir quién es A.

3

El equivalente más cercano a extern int i con una clase es una declaración hacia adelante, lo que se puede hacer tantas veces como se quiera:

class A; 

class A; 

class A; 

class A{}; 

Cuando se define la clase real que son decir cómo es la cantidad de memoria requerido para construir una instancia del mismo, así como también cómo se presenta esa memoria. Sin embargo, ese no es realmente el problema aquí.

1

que puede hacer

class A; 

con la frecuencia que desee y luego en un archivo definirlo con

class A { ... } 

Ejemplo de esto:
classB.h:

class A; 
class B { A *a; } 

classA.h:

class B; 
class A { B *b; } 
+0

Eso no funcionará: el compilador necesita ver la definición de 'B' para calcular el tamaño de 'A'. Sin embargo, los punteros o las referencias funcionarían bien. –

+0

@roger: gracias, corregido. Mi conocimiento de C++ es un poco oxidado – dbemerlin

1

Puede declarar una clase y un objeto varias veces, lo que no puede hacer es definir más de una vez.

extern hace de esta declaración y no una definición (porque no hay inicializador):

extern int a; 

El cuerpo hace que su class una definición y no sólo una declaración. Puedes definir una clase una vez.

+0

Más precisamente extern trata sobre ligamiento. Puede haber definición con extern, como extern int a = 7; –

+0

Sí, pero en este caso el efecto más importante del 'extern' es el hecho de que cambia la declaración para que no sea una definición. –

0

Supongo que la verdadera pregunta es '¿por qué querrías?'. La situación a veces surge cuando incluye un archivo de encabezado varias veces en la misma unidad de traducción (archivo .cpp). Si este es el caso, debe consultar el uso del include guards para mantener al compilador satisfecho.

Otra razón por la que esto podría estar causando problemas para usted es que está utilizando una biblioteca de terceros que define las clases cuyos nombres entran en conflicto con sus propias clases. En este caso, debería considerar el uso de espacios de nombres para resolver la ambigüedad.

En ambos casos 'extern int i;' hace referencia al mismo objeto (declarado en otro lugar) y, por lo tanto, las declaraciones múltiples no son ambiguas. Si usted escribió:.

extern int i; 
extern float i; 

El compilador se queja de la ambigüedad (porque no sabría qué variable que la intención de manipular si escribió 'i = 0;'

declaraciones de clase da lugar duplicados a la posibilidad de que las declaraciones sean diferentes, una vez más, ¿cómo sabe el compilador cuál usar cuando encuentra 'A foo;'? Supongo que el compilador podría comparar las declaraciones de clase y verificar que son de hecho idénticas, pero esto sería un gran esfuerzo para hacer cuando las soluciones alternativas (espacios de nombres, incluir guardias, cambiar el nombre) son mucho más fáciles (y probablemente menos confusas para quien termina leyendo el código).

0

No tiene nada que ver con declaraciones vs definiciones. El problema es tipos versus objetos.

extern int i; 

le dice al programa que en un objeto de tipo int existe, y su nombre es i. Debido a que es extern no se le asigna ningún espacio de almacenamiento aquí, pero en otro lugar, probablemente en otra unidad de traducción, se define y se le asigna almacenamiento.

class A { 
.. 
}; 

define un tipo llamado A. No asigna ningún objeto o variable. No hace absolutamente ninguna diferencia en el tiempo de ejecución, y no se le asigna ningún almacenamiento, porque no es un objeto. Simplemente introduce un nuevo tipo en el compilador. A partir de este momento, puede crear objetos del tipo A y que tendrán asignado el almacenamiento.

0

Lo pensé un poco. Realicé clase en no un tipo de datos, es un habilitador para definir un tipo de datos.

Así que en

extern int i; 
extern int i; 

int es un tipo de datos. Entonces, estamos volviendo a declarar una variable, no un tipo de datos.

Pero en

class A {...}; 
class A {...}; 

A es un tipo de datos. Y estamos redefiniendo un tipo de datos, que no está permitido, por supuesto.

Cuestiones relacionadas