Invalid use of incomplete type struct, even with forward declaration

59,935

Solution 1

For Facility* f = new Facility(); you need a full declaration, not just forward declaration.

Solution 2

To clarify: a forward declaration allows you to operate on an object if very limited ways:

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

Forward declarations can help in some cases. For instance, if the functions in a header only ever take pointers to objects instead of the objects, then you don't need to #include the whole class definition for that header. This can improve your compile times. But the implementation for that header is almost guaranteed to need to #include the relevant definition because you're likely going to want to allocate those objects, call methods on those objects, etc. and you need more than a forward declaration to do that.

Solution 3

Did you #include both area.h and facility.h in foo.cpp (assuming this is the file where you get the error)?

Share:
59,935
robev
Author by

robev

Updated on July 21, 2022

Comments

  • robev
    robev 10 months

    I'm aware of circular dependencies, but even with forward declarations I get this area. What am I doing wrong?

    // 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"
    

    So this compiles fine, but if I do

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

    When I get invalid use of incomplete type struct Area

  • robev
    robev about 12 years
    What do you mean? I thought including in the cpp is good enough?
  • Šimon Tóth
    Šimon Tóth about 12 years
    @robev Including the facility.h should work just fine, unless there are other errors.
  • Mahesh
    Mahesh about 12 years
    @robev - Things will clear up if you show Foo class header and it's source file.
  • robev
    robev about 12 years
    There, fixed. I thought including facility is good enough to get area..I have to include both?
  • Frank Schmitt
    Frank Schmitt about 12 years
    Yes, since you are calling member functions for both Area and Facility instances in your code, you have to.
  • QuantumMechanic
    QuantumMechanic about 12 years
    Yes, you do. Including facility.h only brings in the forward declaration of Area. But since you're using an Area method you need to bring in the full declaration of Area. Which given your setup means you have to include area.h.
  • Šimon Tóth
    Šimon Tóth about 12 years
    @robev If you want area, include area, if you want facility, include facility, it's that simple.
  • mmmmmmmm
    mmmmmmmm about 12 years
    -1: Error comes up in int id = f->getAreaThisIsIn()->getId(); Since calling getId() needs to know about Area. So including area.h is necessary here...not for creating an instance of Facility!