forward declaration with vector of class type - pointer to incomplete class type not allowed

I have two classes, foo and bar.

foo.h #includes bar.h and contains a std::vector of pointers to bar objects. At some point during runtime, bar has to access this vector of pointers to other bar objects. Therefore, foo contains a method named getBarObjects() that returns the array of pointers.

Therefore, I forward declare foo in bar.h. I obviously also have to forward declare the method I'm using - foo::getBarObjects(). As this returns the array of pointers to bar, I get into a vicious cycle.

I cannot forward declare Bar and then simply forward declare getBarObjects(), as this results in "incomplete type name is not allowed".

foo.h:

#include "bar.h"
#include <vector>

class foo {
    public:
         foo();
         ~foo();
         std::vector<bar*> getBarObjects();
    private:
         std::vector<bar*> barObjects;
}

bar.h:

class foo;
std::vector<bar*> foo::getBarObjects();        // error, doesn't know bar at this point

class bar {
    public:
        bar(foo *currentFoo);
        ~bar();
        bool dosth();
    private:
        foo *thisFoo;
}

bar.cpp:

#include "bar.h"

bool bar(foo *currentFoo) {
    thisFoo = currentFoo;
}

bool bar::dosth() {
    thisFoo->getBarObjects();        // error, pointer to inomplete class type is not allowed
}

If I simply include the other way around, I'll have just the same problem in foo later on. Any suggestions?


Solution 1:

You can't forward declare members.

Instead, bar.cpp should #include both foo.h and bar.h. Problem solved.

In general, if you use the sequence:

  • Forward declare all class types
  • Define all class types
  • Bodies of class members

everything will be fine.

Solution 2:

You don't have to include foo.h or bar.h from each other unless you're accessing the internals of either class from the other header file. Declare the classes as needed in the header files, then include both header files from your source file.

foo.h

#include <vector>
class bar;
class foo {
    public:
         foo();
         ~foo();
         std::vector<bar*> getBarObjects();
    private:
         std::vector<bar*> barObjects;
};

bar.h

class foo;
class bar {
    public:
        bar(foo *currentFoo);
        ~bar();
        bool dosth();
    private:
        foo *thisFoo;
}

bar.cpp

#include "foo.h"
#include "bar.h"

bool bar(foo *currentFoo) {
    thisFoo = currentFoo;
}

bool bar::dosth() {
    thisFoo->getBarObjects();
}