bb-generation
bb-generation

Reputation: 1527

C++ destructor problem with boost::scoped_ptr

I have a question about the following code:

#include <iostream>
#include <boost/scoped_ptr.hpp>

class Interface
{
};

class A : public Interface
{
    public:
        A() { std::cout << "A()" << std::endl; }
        virtual ~A() { std::cout << "~A()" << std::endl; }
};


Interface* get_a()
{
    A* a = new A;
    return a;
}

int main()
{
    {
        std::cout << "1" << std::endl;
        boost::scoped_ptr<Interface> x(get_a());
        std::cout << "2" << std::endl;
    }
    std::cout << "3" << std::endl;
}

It creates the following output:

1
A()
2
3

As you can see, it doesn't call the destructor of A. The only way I see to get the destructor of A being called, is to add a destructor for the Interface class like this:

virtual ~Interface() { }

But I really want to avoid any Implementation in my Interface class and virtual ~Interface() = 0; doesn't work (produces some linker errors complaining about a non existing implementation of ~Interface().

So my question is: What do I have to change in order to make the destructor being called, but (if possible) leave the Interface as an Interface (only abstract methods).

Upvotes: 2

Views: 1008

Answers (3)

GManNickG
GManNickG

Reputation: 503825

You must define a virtual destructor in the base class, otherwise you'll get no polymorphic behavior.

And more importantly, you get undefined behavior otherwise; §5.3.5/3:

If the static type of the operand is different from its dynamic type, the static type shall be a base class of the operand’s dynamic type and the static type shall have a virtual destructor or the behavior is undefined.

Emphasis mine.


I'd argue the best is this one:

class Interface
{
public:
    virtual ~Interface(void) = 0;
};

inline Interface::~Interface(void) {}

The compiler can easily inline this, unlike a solution where the implementation resides in a source file. (Speaking of which, this solution doesn't even mandate you have one.) It also leaves the class pure virtual.

Upvotes: 5

James McNellis
James McNellis

Reputation: 355049

You must declare the destructor virtual if you want to delete derived-class objects via a pointer to your base class interface type, and that destructor must have an implementation.

You may still declare it pure virtual, though:

class Interface
{
public:
    virtual ~Interface() = 0;
};

inline Interface::~Interface() { }

Upvotes: 2

SoapBox
SoapBox

Reputation: 20609

You need to define a pure virtual version of the Interface destructor, but you need to also define the body of the destructor. This is a sort of weird case in C++ where even though the function is virtual it must be defined because after the A destructor is called, the Instance destructor will also be called.

Thus the correct answer is:

virtual ~Interface() = 0;

And later, in a cpp file:

Interface::~Interface() {}

Upvotes: 2

Related Questions