Sign in to follow this  
AndyGeers

void* and destructors

Recommended Posts

It seems to be the case that when I keep a void* pointer to a C++ class, the destructor doesn't get called when I delete that object -- is that right? It seems reasonable, but is there any way to get around it besides keeping a separate variable that tells you what type of object the pointer points to, and then casting it immediately before deleting it? (obviously the ideal methods is not to use void* at all but use a common base class that everything else derives from, but I would quite like to be able to point to char arrays as well as CMyClass or whatever)

Share this post


Link to post
Share on other sites
Calling delete on a pointer to a class type cast to a void * has undefined behavior. It will probably just deallocate the memory, but may corrupt your heap. I'd strongly suggest rethinking your design so that you don't use void * at all.

Share this post


Link to post
Share on other sites
delete([])ing a void * is undefined behaviour. Don't do it. Why would you want a variable to point to either a char array or a MyClass? They have absolutely nothing in common so everytime you accessed the variable you'd have to check what type it is. If you're trying to do generic programming then use templates. If you're trying to do object oriented programming then use inheritence. If you're trying to do anything else then leave the type system intact and don't use the void * abomination*.

Enigma

* yes "abomination" is a bit strong, void *s do have some uses.

Share this post


Link to post
Share on other sites
If you could explain exactly what your trying to do i'm sure one of us will suggest a much better alternative.

I'm guessing you are trying to separate allocation/deallocation and construction/destruction for some reason correct?

Share this post


Link to post
Share on other sites
Quote:
Original post by Enigma
delete([])ing a void * is undefined behaviour. Don't do it. Why would you want a variable to point to either a char array or a MyClass? They have absolutely nothing in common so everytime you accessed the variable you'd have to check what type it is. If you're trying to do generic programming then use templates. If you're trying to do object oriented programming then use inheritence. If you're trying to do anything else then leave the type system intact and don't use the void * abomination*.

Enigma

* yes "abomination" is a bit strong, void *s do have some uses.



I'm implementing a datafile system, so some data items will just be strings, some will be 3D meshes, some will be sound effects. It's sort of based upon Allegro's system, if you're familiar with that, where the function making use of the data item knows what type it's looking for, so can cast it. I'm actually trying to be a bit safer than that - I actually have overloaded methods GetDataItem(...) one for each supported data type, and if you ask for a pointer to a sound file but the item is actually a mesh then it returns NULL (so I have all the information necessary to cast my void* pointer to the right type before deleting it, I just wondered if there was an easier way)

Share this post


Link to post
Share on other sites
Quote:
Original post by AndyGeers
It seems to be the case that when I keep a void* pointer to a C++ class, the destructor doesn't get called when I delete that object -- is that right? It seems reasonable, but is there any way to get around it besides keeping a separate variable that tells you what type of object the pointer points to, and then casting it immediately before deleting it? (obviously the ideal methods is not to use void* at all but use a common base class that everything else derives from, but I would quite like to be able to point to char arrays as well as CMyClass or whatever)
If you want to be able to point to char arrays as well, then:
Make an empty base class "CMyBaseClass".
Make a simple class "CMyCharArrayClass" that only has a char array as it's private member and define the [] operators. Write whatever other methods you require in this class.
Derive CMyCharArrayClass from CMyBaseClass.
Derive CMyClass from CMyBaseClass.

Now, only deal with CMyBaseClass pointers.

Share this post


Link to post
Share on other sites
Quote:
Original post by AndyGeers
I'm implementing a datafile system, so some data items will just be strings, some will be 3D meshes, some will be sound effects.


I see no reason to create a single class which contains a single void pointer to any number of discrete objects. You might want to consider using an abstract factory.


EDIT: Should be 'contains a single void pointer'

[Edited by - Helter Skelter on July 9, 2005 6:19:54 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by AndyGeers
I'm implementing a datafile system, so some data items will just be strings, some will be 3D meshes, some will be sound effects. It's sort of based upon Allegro's system, if you're familiar with that, where the function making use of the data item knows what type it's looking for, so can cast it. I'm actually trying to be a bit safer than that - I actually have overloaded methods GetDataItem(...) one for each supported data type, and if you ask for a pointer to a sound file but the item is actually a mesh then it returns NULL (so I have all the information necessary to cast my void* pointer to the right type before deleting it, I just wondered if there was an easier way)


Do you need to delete any of the items early? Or are you just looking for garbage collection?

If you're just looking to clean up objects when the app exits, why not use smart pointers at the point of instantiation, and when the instantiator goes out of scope, it will automatically delete all your dynamically created class objects. Then all you have to do is keep track of your arrays.

The point of instantiation is the key, though. That's where you know the type of what it is you're creating.

Really, if all you're doing is keeping the list of (void *) around for deletion purposes, it sounds like you're wanting garbage collection... nothing more.

Share this post


Link to post
Share on other sites
Quote:
Original post by garyfletcher
templates..it's the future!!!



Back when I was with Disney someone asked me "why bother using templates?"

Since I was already annoyed by this person I gave the quickest most logical answer: "Why spend hours duplicating implementations when you can use templates and confuse your coworkers for MUCH longer?"


Believe it or not it worked. They never asked me that question again :)

Share this post


Link to post
Share on other sites
Ah...so you haven't heard of an english comedian called Peter Kay and the superb series he did, Phenix Nights...it's a reference to a joke about Garlic Bread. "garlic bread, GARLIC, BREAD!!!" - "It's the future, I've seen it"

You had to be there!!!

Anyway...back to reality. This does sound like a job for a object factory...maybe you should take a look at this GameDev article about Generic object factories.

You'll have to add in a little extra code to track/delete your entities in a std::vector<> if you need to clean them up afterward, and maybe a little reference counting et all...but it's a start..hopefully..:)

Share this post


Link to post
Share on other sites
Quote:
Original post by Verg
If you're just looking to clean up objects when the app exits, why not use smart pointers at the point of instantiation, and when the instantiator goes out of scope, it will automatically delete all your dynamically created class objects. Then all you have to do is keep track of your arrays.


That's actually the best suggestion so far, thanks for that.

I really can't think of way that templates could be useful for this particular problem, except for the discriminated unions approach.

Share this post


Link to post
Share on other sites
Quote:
Original post by Helter Skelter
Quote:
Original post by AndyGeers
I'm implementing a datafile system, so some data items will just be strings, some will be 3D meshes, some will be sound effects.


I see no reason to create a single class which contains a single void pointer to any number of discrete objects. You might want to consider using an abstract factory.


EDIT: Should be 'contains a single void pointer'


Why is a factory necessary though? Creating the items isn't the problem, it's deleting them...

Share this post


Link to post
Share on other sites
A factory isn't really necessary, it just helps if you're creating an unknown number of unknown classes at runtime. If, for example, you were building your game /level based on data in an external file. You'd register the class with the factory and then whenever you needed one you'd get the factory to create it and pass back a pointer to it.

If you just need to track memory so you can clean everything up afterwards then an object factory isn't what you want.

Personally I use vectors to track the classes I instansiate. Which means I have 6 vectors to run through when my engine is deleted. Oh, except for my dynamically called functions and arguments where I use a vector for the functions and a map of vectors for the associated arguments.

void* is widely used in C, but not so much in C++. Think it freaks people out..:)

Smart pointers seem like a way to go as well..:)

Anyway, good luck.

Share this post


Link to post
Share on other sites
Quote:
Original post by garyfletcher
void* is widely used in C, but not so much in C++. Think it freaks people out..:)


its not that it freaks people out its because there is no type saftefy, can cause subtle hard to find bugs, anti-patterns such as nasty type switching code leading to maintenance nightmares etc.

Share this post


Link to post
Share on other sites
Rightio...wasn't recommending the use of void* while using C++

Unfortunatley, in C, their use is enevitible in some instances..and coming from a C background some of us are used to seeing them in code..sorry about that.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this