2011-04-04 13 views
11

Conozco las dependencias circulares, pero incluso con las declaraciones de reenvío obtengo esta área. ¿Qué estoy haciendo mal?Uso no válido de estructura de tipo incompleta, incluso con la declaración de reenvío

// facility.h 
class Area; 

class Facility { 
public: 
    Facility(); 
    Area* getAreaThisIn(); 
    void setAreaThisIsIn(Area* area); 
private: 
    Area* __area; 
}; 

// facility.cpp 
#include "facility.h" 
#include "area.h" 
{ ... } 

// area.h 
class Facility; 
class Area { 
public: 
    Area(int ID); 
    int getId(); 

private: 
    std::list<Facility*> _facilities; 
}; 

// area.cpp 
#include "area.h" 
#include "facility.h" 

Así que esto compila bien, pero si lo hago

// foo.h 
#include "facility.h" 
class Foo { .. }; 

// foo.cpp 
#include "foo.h" 
void Foo::function() { 
    Facility* f = new Facility(); 
    int id = f->getAreaThisIsIn()->getId(); 

Cuando llego invalid use of incomplete type struct Area

+3

¿Ha incluido ** area.h ** en el archivo que está definiendo 'Foo :: function()'? –

+0

He intentado compilar esto con g ++ (agregando definiciones de stub de los métodos 'Facility' y' Area') después de corregir el error tipográfico 'getAreaThisIn()' en 'facility.h' (debería ser' getAreaThisIsIn() ') y compilado para mí. Aunque mi 'Foo.cpp' sí incluía ambos encabezados. – QuantumMechanic

+3

Tenga en cuenta que los identificadores que comienzan con dos guiones bajos ('__rea' lo estoy mirando) están reservados por la implementación y no deben utilizarse. –

Respuesta

8

Para Facility* f = new Facility(); necesita una declaración completa, no sólo declaración adelantada.

+0

¿A qué te refieres? Pensé que incluir en el cpp es lo suficientemente bueno? – robev

+1

@robev Incluir el 'facility.h' debería funcionar bien, a menos que haya otros errores. –

+1

@robev - Las cosas se aclararán si muestra el encabezado de la clase 'Foo' y su archivo de origen. – Mahesh

4

¿Incluyó #include area.hy facility.h en foo.cpp (suponiendo que este es el archivo donde se obtiene el error)?

+0

No, tengo que incluir ambos? – robev

+3

Sí, ya que está llamando a funciones miembro para las instancias Área e Instalación en su código, tiene que hacerlo. –

19

Para aclarar: una declaración hacia adelante le permite operar en un objeto si de manera muy limitada:

struct Foo; // forward declaration 

int bar(Foo* f); // allowed, makes sense in a header file 

Foo* baz(); // allowed 

Foo* f = new Foo(); // not allowed, as the compiler doesn't 
        // know how big a Foo object is 
        // and therefore can't allocate that much 
        // memory and return a pointer to it 

f->quux(); // also not allowed, as the compiler doesn't know 
      // what members Foo has 

declaraciones adelantadas pueden ayudar en algunos casos. Por ejemplo, si las funciones en un encabezado solo toman punteros a los objetos en lugar de los objetos, entonces no es necesario que #include toda la definición de clase para ese encabezado. Esto puede mejorar tus tiempos de compilación. Pero la implementación de ese encabezado casi seguro necesita #include la definición relevante porque es probable que desee asignar esos objetos, llamar a métodos en esos objetos, etc. y necesita más que una declaración directa para hacer eso.

Cuestiones relacionadas