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
.
精彩评论