Archived

This topic is now archived and is closed to further replies.

Inherited Objects Deconstructors

This topic is 5312 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

OK, ill try to keep this as simple as possible. Say i have a base class for 3d objects. This class is mainly used to load up models and display them onscreen. Now i inherited a Player class from the base class. I intend to allow the player class to have other properties like hp,mana, and other functions and variables. Since different models have different number of vertices, textures, etc.., i dynamically allocate memory during the loading process. The data is then deleted via the deconstructor. Now that i have a derived class, i can use the load,display functions without any problems. But my question is whether the base class deconstructor is called when the player class is destroyed or do i have to specify all the delete commands again the player class deconstructor. I cant seem to be able to do this, because the pointer is private in the base class and the deconstructor of the Player class doesnt seem to have access to it.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Try declaring the base class destructor virtual. It seems like that has come up for me before and that worked.

class blah{
public:
blah();
virtual ~blah();
};

Share this post


Link to post
Share on other sites
I still use my base class to define other objects so i cannot declare it''s deconstructor virtual.

Im not sure what virtual does but i think it''s supposed to be empty.

Share this post


Link to post
Share on other sites
quote:
Original post by GamerSg
I still use my base class to define other objects so i cannot declare it''s deconstructor virtual.



Sure you can.

quote:

Im not sure what virtual does but i think it''s supposed to be empty.



Virtual functions allow derived classes to specify their own implementation of the functions, including destructors. The catch is, as you have to worry about, is that sometimes you want a derived class to use the base class''s implementation. Here are three options:

1. duplicate the code in the derived class''s function (YUCKY, DON''T DO THIS).

2. In the base class, create a ''protected'' function that handles the code you want shared (in this case, the deallocation), and DON''T make this virtual. Then just call this function from both destructors. (YUMMY, DO THIS).

3. Call the base class destructor from the derived class destructor, just by calling BaseClass::~BaseClass(); inside your DerivedClass destructor. Can lead to a few weird complications if you''re not careful.

Share this post


Link to post
Share on other sites
Hmm i tried the protected function. It compiled and worked.

But when i exited the application, i got an error pointing to the line

/* verify block type */
_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));

in dbgdel.cpp.





Share this post


Link to post
Share on other sites
That could be any of a million things. Basically, you have a memory problem, likely trying to free the same memory twice. If you''re using the protected, non-virtual cleanup function in the base class (called from the destructor) to delete the memory, the base class destructor should still be virtual, and the derived class destructor should NOT call the base class destructor but instead call the protected cleanup function.

If you''re sure you''re doing that right, than the error could be anything, it''s hard to tell without the code. Easiest would be for you to run it in a debugger, and then when you hit the error, look at the call stack to see which variable of yours, and where it is used, is causing the problem and then start tracing backwards.

Share this post


Link to post
Share on other sites
Ok i ran it in debug mode and to my surprise,
the derived class''s deconstructor was called first.
Nothing unsual here.

So it called the protected cleanUp();

But, after it had cleaned up, it went on to call the base class deconstructor even though i have not called the deconstructor or specified any base class object.

Share this post


Link to post
Share on other sites
quote:
Original post by BriTeg
the base class destructor should still be virtual, and the derived class destructor should NOT call the base class destructor but instead call the protected cleanup function.




From my knowledge, the derived class does not inherit the deconstructor of the base class. So am i right to say that it need not be virtual.

And from my debugging, i realise that the derived class automatically calls the base class deconstructor.

Pls correct me if im wrong.

Another qsn: If you did not delete a block of memory, would the OS clear up after u exit the application.

Share this post


Link to post
Share on other sites
Hokey crap, I''ve led you down the garden path. I whipped up a quick test program, and it looks like I was completely wrong. The derived class''s destructor *will* call the base class destructor, regardless if it is virtual or not. This is not how other member functions work, I guess it''s only for the destructor.

So, forget everything I said. Delete your stuff in your base class destructor (or even keep that protected cleanup function, it''s handy if you want to reset your object without destroying it), and make your derived contructor completely empty (unless the derived class does extra memory allocation of its own).

Sorry again for the wrong information, I feel bad.

Share this post


Link to post
Share on other sites
Let''s take an example : class B inherits from A.

Whether the destructors are virtual or not, whenever B::~B()
is called, A::~A() is called right after. So you do NOT have
to reimplement A::~A() in B::~B().

Now, here''s what the virtual destructor changes. Say you write the following code :

A* a = new B();

delete a;

If both destructors are virtual, "delete a" will invoke B::~B(). If they are not, "delete a" will invoke A::A() (which is probably not what you want).

There is a simple rule : if there are virtual methods in a class (or in its base class) the destructor must be defined virtual.

Hope it helps.

Share this post


Link to post
Share on other sites
quote:
Original post by BriTeg
Hokey crap, I''ve led you down the garden path. I whipped up a quick test program, and it looks like I was completely wrong. The derived class''s destructor *will* call the base class destructor, regardless if it is virtual or not. This is not how other member functions work, I guess it''s only for the destructor.

So, forget everything I said. Delete your stuff in your base class destructor (or even keep that protected cleanup function, it''s handy if you want to reset your object without destroying it), and make your derived contructor completely empty (unless the derived class does extra memory allocation of its own).

Sorry again for the wrong information, I feel bad.


Lol.
It''s OK. Thx for the help anyway. I would probably have been sleeping(Midnite now) if you had not replied to my post and i would never have solved this.

Share this post


Link to post
Share on other sites
quote:
Original post by rodzilla
Let''s take an example : class B inherits from A.

Whether the destructors are virtual or not, whenever B::~B()
is called, A::~A() is called right after. So you do NOT have
to reimplement A::~A() in B::~B().

Now, here''s what the virtual destructor changes. Say you write the following code :

A* a = new B();

delete a;

If both destructors are virtual, "delete a" will invoke B::~B(). If they are not, "delete a" will invoke A::A() (which is probably not what you want).

There is a simple rule : if there are virtual methods in a class (or in its base class) the destructor must be defined virtual.

Hope it helps.


So virtual deconstructors are only required if you use polymorphism in ur app?

Im not comfortable with polymorphism and i cant think of a reason why anyone would need it when inheritance can do it.It would be nice to tell me the advantages of polymorphism over inheritance.

Share this post


Link to post
Share on other sites
Only one rule : whenever you use virtual methods, the destructor must be virtual.

As for using polymorphism, say you have "drawable" things. Some
"drawable"s will be, say, "model"s. Other "drawable"s could be, say, "particle_systems".

When you will render your "drawable"s, there are 2 options :

- you put all "drawable"s in a list (of drawable*) and the draw methods must be virtual.

- the draw methods are non-virtual and you have to use separate strong-typed lists (a list of model*, a list of particle_system*...).

This example is probably not relevant, but I hope you get the idea.

Be careful anyway, calling a virtual method has a tiny cost.
It''s probably not a good thing to make a million virtual calls per frame.

Share this post


Link to post
Share on other sites
quote:
Original post by rodzilla
Only one rule : whenever you use virtual methods, the destructor must be virtual.



One question though: if you use virtual methods in your base class, those methods in your derived class are virtual whether or not you specify "virtual" explicitly. Why does this not also happen for destructors?

Share this post


Link to post
Share on other sites
I''m not sure there''s a good reason for this.

Of course, the destructor is a very special method, because
when you call it (via delete or when exiting a block), all destructors in the class hierarchy will be invoked.

BTW, when redefining a virtual method (in a child class), you should use the "virtual" keyword. It doesn''t change anything as far as the compiler is concerned, but it make the code more readable.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Sounds more like you are using inheritance when it''s not needed.

The simple way to do this is rather have apointer in the player class that points to the 3D object. This allows more freedom.
The object has the routines for movement transformation and so on. The base position is handled by the player class. The offset positions are handled by the object.
This way the person can change what object they are controlling and so on. Lets say your character what''s to drive a vehicle.
all you have to do is swap the erase the previous boject and load a new one and give the pointer to the player class.


class point
{
float x,y,z;
}

class Object3D
{
int number vertices;
point *vert;
/*and so on */
}


class player
{
int health;
float x,y;
Object3D *p;
}


in herantance would be better used in something like building NPC VS chracters.

With the above methode I gave you manage the memory you need to call what ever destructors to get rid of the lower classes. Example: the points that are used would need to be called then the object. Make dynamic arrays to the sub classes rather than inherit them.

the other thing the It makes more sence to have a object as a sub set of a character rather than the other way around. The character may change objects the object wont change chracters. Even if the same type of object is used for many characters.

Hope I haven''t confused you to much

Share this post


Link to post
Share on other sites