开发者

Where to delete?

I'm having quite a hard time deciding on the best way to delete my derived classes here. I currently have the following layout:

class Tag {
   // Stuff
   // [...]
   void releaseMemory(Tag *t);
};

class TagByte : public Tag { /* [...] */ };
class TagShort : public Tag { /* [...] */ };

Tag::releaseMemory(Tag *t) {
    switch (t->getType()) {
       case TAG_BYTE:  delete (TagByte *)t; return;
       case TAG_SHORT: delete (TagShort *)t; return;
       // [...] many more
    }
}

The reason I am doing this is that there are more complex tags like TagCompound which will contain tags of different types, and all of those are stored as a Tag *. Inside the destructors ~TagCompound, ~TagList I do call Tag::releaseMemory(); on every tag, because delete on a Tag * would only free a Tag and not the actual TagWhatever, thus resulting in a memory leak.

The other option I had thought of was adding a new virtual method to every derived class, so every child of Tag would have it's own releaseMemory() instead of one combined in the super class.

Then I wonde开发者_C百科red whether I'm already starting off bad on the design level by assuming everything passed into the complex types TagCompound and TagList is a heap object to which I also couldn't find a better solution, because this whole construct is part of a parser for something that looks like this (just binary and not as verbose):

TAG_Compound("Root"): 4 entries
{
  TAG_String("Name"): Test
  TAG_Short("SomeNumber"): 21
  TAG_Double("..."): 9000.5
  TAG_Compound("Eek!"): 2 entries
  {
    TAG_String("Marco"): Polo
    TAG_List("Names"): 3 entries of type String
    {
      TAG_String: Hello
      TAG_String: World
      TAG_String: Segfault
    }
  }
}

And dynamically reading that on runtime doesn't play well with instances on the stack.

What can I do to make this... I don't know.. elegant?


Generally, you just declare a virtual destructor in the base class. This plays nice with both stack and heap allocation. In case of polymorphic delete, the compiler figures out the true type and calls its destructor.


This design really breaks the idea of encapsulation. Tag should never know that TagByte exists. The destructor for Tag should be marked as virtual as should the destructor of each derived class. Release allocated variables for each level in the appropriate destructor. At destruction everything will be cleaned up in the correct order with no memory leaks. My feeling is this design is bad from the start and you should read up on destructors and inheritance.


C++ actually offers very elegant solution to this - virtual destructor. Even more, every polymorphic type should have one. GCC even has a warning level for this -Wnon-virtual-dtor.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜