Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++: auto_ptr + forward declaration?

I have a class like this:

class Inner;

class Cont
{
public:
    Cont();
    virtual ~Cont();
private:
    Inner* m_inner;
};

in the .cpp, the constructor creates an instance of Inner with new and the destructor deletes it. This is working pretty well.
Now I want to change this code to use auto_ptr so I write:

class Inner;

class Cont
{
public:
    Cont();
    virtual ~Cont();
private:
    std::auto_ptr<Inner> m_inner;
};

Now, the constructor initialized the auto_ptr and the destructor does nothing.

But it doesn't work. the problem seem to arise when I'm instantiating this class. I get this warning:

warning C4150: deletion of pointer to incomplete type 'Inner'; no destructor called

Well, this is obviously very bad and I understand why it happens, The compiler doesn't know about the d'tor of Inner when instantiating the template of auto_ptr<Inner>

So my question: Is there a way to use auto_ptr with a forward declaration like I did in the version that uses just plain pointers?
Having to #include every class I declare a pointer to is a huge hassle and at times, just impossible. How is this problem usually handled?

like image 646
shoosh Avatar asked Dec 23 '09 10:12

shoosh


3 Answers

You need to include the header defining class Inner into the file where Cont::~Cont() implementation is located. This way you still have a forward declaration in teh header defining class Cont and the compiler sees class Inner definition and can call the destructor.

//Cont.h
class Inner; // is defined in Inner.h
class Cont 
{ 
    virtual ~Cont(); 
    std::auto_ptr<Inner> m_inner;
};

// Cont.cpp
#include <Cont.h>
#include <Inner.h>

Cont::~Cont()
{
}
like image 138
sharptooth Avatar answered Sep 28 '22 15:09

sharptooth


Turns out the problem occurs only when I make the c'tor inline. If I put the c'tor in the cpp, after the decleration of Inner everything's ok.

like image 24
shoosh Avatar answered Sep 28 '22 16:09

shoosh


You may consider boost::shared_ptr() instead. It has no practical disadvantages instead of performance, and is much more friendly to forward declarations:

boost::shared_ptr<class NeverHeardNameBefore> ptr;

is okay, without extra declarations above.

shared_ptr does more than auto_ptr, such as reference counting, but it should not harm if you don't need it.

like image 35
Pavel Radzivilovsky Avatar answered Sep 28 '22 15:09

Pavel Radzivilovsky