Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Alternative to forward declarations when you don't want to #include

I usually, almost without thinking anymore, use forward declarations so that I won't have to include headers. Something along this example:

//-----------------------
// foo.h
//-----------------------
class foo
{
   foo();
   ~foo();
};


//-----------------------
// bar.h
//-----------------------

class foo; // forward declaration

class bar
{
   bar();
   ~bar();

   foo* foo_pointer;
};

Some developers like to use this method to avoid problems with inclusion circles. I rather use it to minimize the overhead in extensive inclusion hierarchies, an important part of physical design (for larger projects in particular).

However, in some cases I really like to declare members as normal objects instead of pointers to benefit from the automatic construction/destruction mechanism. This leads to the problem that forward declarations can't be used anymore, since the compiler needs the class definition in such case, eg:

//-----------------------
// foo.h
//-----------------------
class foo
{
   foo();
   ~foo();
};


//-----------------------
// bar.h
//-----------------------

class foo;       // Not enough given the way we declare "foo_object"..
#include "foo.h" // ..instead this is required

class bar
{
   bar();
   ~bar();

   foo foo_object;
};

So, I would be happy if anyone knows an alternative language construct which can be used here so that I can declare "foo_object" as shown in the example, but without including its header.

Regards

/Robert

like image 306
sharkin Avatar asked Nov 20 '08 16:11

sharkin


1 Answers

Just use a smart pointer - you can even use auto_ptr in this case.

//-----------------------
// bar.h
//-----------------------

#include <memory>
class foo;       // Not enough given the way we declare "foo_object"..

class bar
{
public:
   bar();
   ~bar();

   foo &foo_object() { return *foo_ptr; }
   const foo &foo_object() const { return *foo_ptr; }

private:
   auto_ptr<foo> foo_ptr;
};

You get all the benefits of automatic memory management, without having to know anything about foo in bar.h. See Wrapping Pointer Data Members for Herb Sutter's recommendation.

If you really want default construction to happen automatically, try this:

#include <iostream>
using namespace std;

class Foo;

template <typename T>
class DefaultConstuctorPtr
{
    T *ptr;
    void operator =(const DefaultConstuctorPtr &);
    DefaultConstuctorPtr(const DefaultConstuctorPtr &);

public:
    DefaultConstuctorPtr() : ptr(new T()) {}
    ~DefaultConstuctorPtr() { delete ptr; }

    T *operator *() { return ptr; }
    const T *operator *() const { return ptr; }
};

class Bar
{
    DefaultConstuctorPtr<Foo> foo_ptr;
public:
    Bar() {} // The compiler should really need Foo() to be defined here?
};

class Foo
{
public:
    Foo () { cout << "Constructing foo"; }
};

int main()
{
    Bar bar;
}
like image 99
5 revs Avatar answered Nov 15 '22 19:11

5 revs