views:

1214

answers:

2

I'm trying to simplify a bunch of header file "include spaghetti" by using forward declarations and moving #includes into the implementation file. However, I keep coming upon the following scenario:

//Foo.h
#include "Bar.h"

class Foo
{
public:
  void someMethod(Bar::someType_t &val);
};

//Bar.h
.
.
.
class Bar
{
public:
  typedef std::vector<SomeClass> someType_t;
};

I want to remove #include "Bar.h" in as many cases as possible. I also see the situation where the typedef in Bar.h is listed outside of the Bar class. I'm assuming both situations can be addressed in the same manner.

Any ideas?

A: 

Just use class Bar;. That tells C++ you're declaring your intention to define Bar.

Charlie Martin
Note the typedef inside `class Bar`... this is the real problem, not the class itself which could be addressed by the forward declaration that you suggested.
Naaff
+3  A: 

Unfortunately you don't have many choices and none is perfect.

First, the two obvious and unacceptable solutions:

  • You can forward declare the typedef which totally defeats the purpose of using a typedef.
  • You include the file which contains the typedef, which you want to avoid.

The the more interesting solutions:

  • Have all related typedefs in the same include and include that file. This creates code coupling between the classes though. You ought to do that only with related classes, else you are going to end up with a god include file and this could lead to a lot of recompiling when you add a typedef to that file.
  • For each class, have a separate include with the typedefs in it. Kind of annoying, but it works.

Those last two are like doing forward declarations but with added typedefs. They reduce file interdependencies since you are rarely modifying the typedef file.

I'd say for most situation, the central include has the most benefit for hassle. Just be careful.

Coincoin
I think I may perform a 4th option:- Declare the same exact typedef in Foo.hMy reasoning is that Foo is presenting it's own interface to clients, and is responsible for how it's own methods are called. Client software won't have to include bar.h or have any knowledge of it. This level of encapsulation and low coupling is the target I'm aiming for.
Tim Rupe
Oops. I meant to say 5th option.
Tim Rupe