Question

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

Was it helpful?

Solution

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;
}

OTHER TIPS

You can't. The compiler needs to know the size of the object when declaring the class.

References are an alternative, although they have to be instantiated at construction time, so it's not always feasible.

Another alternative are smart pointers, but I suppose that's technically still a pointer.

It would be good to know why you don't want to use a pointer to suggest some other construct though...

What you want cannot be done in C++. In order to generate code for an object, your compiler needs to know how much storage its class requires. In order to know that, it must know how much storage is required for each member of the class.

If you want to create a class of type bar with a member of type foo, the compiler has to know how big a foo is. The only way it knows that is if it has the definition of foo available (via #include). Otherwise, your only option is to use a forward-declaration of foo and a pointer or reference instead of an actual foo object.

As others stated you cannot do it for reasons they stated too :) You then said you don't want to care about the member construction / destruction in the class containing them. You can use templates for this.

template<typename Type>
struct member {
    boost::shared_ptr<Type> ptr;
    member(): ptr(new Type) { }
};

struct foo;
struct bar {
    bar();
    ~bar();

    // automatic management for m
    member<foo> m;
};

I think the code is self explanatory. If any questions arise, bug me please.

There's no way around that.

Your best bet is to limit how much is included, but you have to include the file with the class declaration. You could could split the class declarationout into a separate header which, hopefully, includes nothing else. Then yes, you have to have an #include, but you're still keeping your include hierarchy somewhat shallow. After all, including one file is cheap, it's only when the hierarchy stretches out to hundreds or thousands of files that it starts hurting... ;)

Pretty much the only thing you can do is minimize the impact by using the pImpl idiom so that when you include foo.h, you're only including foo's interface.

You can't avoid including foo.h, but you can make it as cheap as possible. The habit you've developed of using foward declarations rather than #inlcudes has you well on this path.

If you are able to use a reference, you can retain the same use syntax. However, your reference has to be initialised straight away in the constructor, so your ctor absolutely must be defined out-of-line. (You will also need to free the object in the destructor too.)

// bar.h
class foo;

class bar {
    foo& foo_;

public:
    bar();
    ~bar();
};

// bar.cc
bar::bar() : foo_(*new foo)
{
    // ...
}

bar::~bar()
{
    // ...
    delete &foo_;
}

Your mileage may vary. :-)

You could use a custom "smart pointer" class which automatically creates and destroys an instance. This would acheive the automatic construction and destruction you are after.

To prevent the need for another #include, you can include this myAuto class in the prefix header for your project, or you can copy and paste it into every header (not a good idea, but it would work).

template<class T>
class myAuto
{
    private:
        T * obj;

    public:
        myAuto() : obj(new T) {  }
        ~myAuto() { delete obj; }
        T& object() { return *obj; }
        T* operator ->() { return obj; }
};

Here is how you would use it:

// foo.h:
class foo
{
    public:
        foo();
        ~foo();
        void some_foo_func();
};
//bar.h:
class foo;
class bar
{
    public:
       bar();
       ~bar();
       myAuto<foo> foo_object;
};
//main.cc:
#include "foo.h"
#include "bar.h"

int main()
{
    bar a_bar;

    a_bar.foo_object->some_foo_func();

    return 0;
}

You could also use the pImpl idiom, e.g.:

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


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

class foo;

class bar
{
private:
    struct impl;
    boost::shared_ptr<impl> impl_;
public:
    bar();

    const foo& get_foo() const;
};

//-----------------------
// bar.cpp
//-----------------------
#include "bar.h"
#include "foo.h"

struct bar::impl
{
    foo foo_object;
    ...
}

bar::bar() :
impl_(new impl)
{
}

const foo& bar::get_foo() const
{
    return impl_->foo_object;
}

You still get the benefits of forward declarations, plus you hide your private implementation. Changes to the implementation of bar won't necessarily require compiling all the source files that #include bar.h. The implementation struct itself is self-contained in the .cpp file and here you can declare objects to your hearts content.

You have a small performance hit because of pImpl itself, but depending on the application this might not be a big deal.

I have used the pImpl idiom for large projects and it makes a big difference to compile times. Pity the language cannot handle a truly private implementation, but there you have it.

There are really only three alternatives to associate two objects. You already discovered two: embed Foo in Bar, or put Foo on the heap and put a Foo* in Bar. The first requires defining class Foo before defining class Bar; the second merely requires you to forward declare class Foo.

A third option does exist, which I only mention because you specifically exclude both previous options in your question. You can (in your .cpp) create a static std::map. In every Bar constructor you add a Foo to this map, keyed on this. Every bar member can then find the associated Foo by looking up this in the map. Bar::~Bar will call erase(this) to destroy the Foo.

While this keeps sizeof(Bar) unchanged, the actual memory use is higher than including a Foo* in Bar. You still might do this if binary compatibility is a pressing concern, though.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top