4

I have a problem using a C++ map to store pointers to a base class and some derived class.

Let me explain by a rather long but simple code:

#include <map>
#include <iostream>

struct foo{ int dummy[4]; };
struct bar{ int additionnal[4]; };

class Base
{
private:
    struct foo *_internal_structure;
public:
    Base() { _internal_structure = new struct foo; }
   ~Base()
   {
        delete _internal_structure;
        std::cout << "Base DTOR\n";
   }
};

class Derived: public Base
{
private:
    struct bar *_additional_structure;
public:
    Derived() { _additional_structure = new struct bar; }
   ~Derived()
   {
        delete _additional_structure;
        std::cout << "Derived DTOR\n";
   }
};


int main(int argc, char *argv[])
{
    std::map<int, Base*> my_map;
    Base *to_add = new Base();
    Derived *derived_to_add = new Derived();
    my_map[1] = to_add;
    my_map[2] = derived_to_add; // works, derived class, but object gets sliced

    /// clear hash map ///
    std::map<int, Base*>::const_iterator iter;
    for(iter = my_map.begin(); iter != my_map.end(); ++iter)
    {
        delete (*iter).second;
    }

    return 0;
}

Result when run:

Base DTOR
Base DTOR

So, thing is, when I insert a Derived class pointer into my map, the underlying object is considered as a Base class; so the destructor called is the one of the Base class, and not the Derived class. Valgrind confirms me that I loose 16 bytes every time.

Also, I can't use Boost's shared_ptr (I saw some mentions of it here), and the embedded architecture I use doesn't support C++ exceptions and RTTI (which in my case, causes some unaligned accesses and other bad stuff)(edit: not related).

Do you know how I can fix this behavior?

Community
  • 1
  • 1
Gui13
  • 12,993
  • 17
  • 57
  • 104
  • Not related to your question, but those data members should be `boost::scoped_ptr` or `const std::auto_ptr` instead of plain pointers. – Tadeusz Kopec for Ukraine Jun 22 '11 at 14:58
  • @Tadeusz: I can't use boost, I say it in the last paragraph :) I'll look into auto_ptr, thanks. – Gui13 Jun 22 '11 at 15:20
  • newer compilers have some stuff propagated from Boost into the new C++ standard that would be helpful - see `std::unique_ptr` or `std::shared_ptr` if you are on current Visual C++ (or GCC I think). – Steve Townsend Jun 22 '11 at 15:23

2 Answers2

13

Where is your virtual destructor???!!!

Read this, and never forget. Really, you have just broken one of the 10 C++ commandments... :))

Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
6

Your destructor in any base class should be virtual.

Otherwise it's impossible at runtime to determine what destructor(s) should actually be called, in the case where subclasses are referenced through a pointer to their base class.

Steve Townsend
  • 53,498
  • 9
  • 91
  • 140