views:

152

answers:

3

I have two classes and both of them uses some of the other class, on example:

// class1.h
class Class1;
#include "class2.h"

class Class1 {
  public:
  static Class2 *C2;
  ...
};

// class2.h
class Class2;
#include "class1.h"

class Class2 {
  public:
  static Class1 *C1;
  ...
};

And when I define it like in example above, it works (I also have some #ifndef to avoid infinite header recurency). But I also want to add some inline functions to my classes. And I read here that I should put definition of inline function in header file, because it won't work if I'll put them in cpp file and want to call them from other cpp file (when I do it I get undefined reference during linking). But the problem here is with something like this:

// class1.h
...
inline void Class1::Foo() {
  C2->Bar();
}

I get error: invalid use of incomplete type ‘struct Class2’.

So how can I do it?

+1  A: 

You have it mix'd up. What you want is:

// class1.h
class Class2;

class Class1 {
  public:
  static Class2 *C2;
  ...
};

// class2.h
class Class1;

class Class2 {
  public:
  static Class1 *C1;
  ...
};

And include the respective headers in the source. The line:

class Class1; // or Class2

Declares an incomplete type, and you can have pointers and references to incomplete types. Upon usage, though, it needs to be complete. So just say "hey it'll exist!" in the header, and in the source tell it what it is.

GMan
Thanks. I fixed it, but the problem with inline is still the same.
klew
+3  A: 

You need to delay including the header, but then include it and define your inline methods. By doing this in each header, they are self-sufficient and including one will always include the other, with include guards preventing infinite recursion.

A.hpp

#ifndef INCLUDE_GUARD_B9392DB18D114C1B8DFFF9B6052DBDBD
#define INCLUDE_GUARD_B9392DB18D114C1B8DFFF9B6052DBDBD

struct B;

struct A {
  B* p;
  void foo();
};

#include "B.hpp"

inline
void A::foo() {
  if (p) p->bar();
}

#endif

B.hpp

#ifndef INCLUDE_GUARD_C81A5FEA876A4C6B953D1EB7A88A27C8
#define INCLUDE_GUARD_C81A5FEA876A4C6B953D1EB7A88A27C8

struct A;

struct B {
  A* p;
  void bar();
};

#include "A.hpp"

inline
void B::bar() {
  if (p) p->foo();
}

#endif
Roger Pate
Thanks! Works great! It's very nice to see about 8% speed improvement! :)
klew
A: 

My suggestion is that you place common methods and members into a base class, then derive C1 and C2 from the base class. This may fix the circular dependency issue.

Thomas Matthews