Archived

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

C++ Destructor problem

This topic is 6358 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

Howdy I'm running into a bit of trouble with C++ destructors. This is probably a fairly simple thing... but it's irritating me and I've never noticed the problem before. I have two classes, A and B. Each has a constructor and destructor defined. B is inherited from A. I have a pointer to A in my program which is assigned to point to an object of type B. This calls the constructor of B which calls the constructor of A, executes itself, and returns. However, when I destroy the object, because the pointer is of type A, only the destructor of A is run, and not the destructor of B. If I make the pointer of type B, it works fine. I have included a little code snippet so you can see what I am talking about (assume classes A and B are defined):
    

A *aptr = new B();

delete aptr;   // this line does not call B's destructor, only A's

// however...


B *bptr = new B();

delete bptr;   // this line calls B's destructor then A's


    
I'm sure this is something simple, maybe even correct C++, but I'm not 100% on the C++ standard so any advice would be appreciated on how I can make the code call B's destructor. I'm using MSVC 5. Thanks! Starfall Edited by - Starfall on 7/13/00 2:50:56 PM

Share this post


Link to post
Share on other sites
define A''s destructor as
virtual ~A();

i haven''t tried that with destructors, but i had the similar problem with a method inside my classes and i was told to define it as virtual in the base class, so i did and it worked perfectly. i think it''s the same thing for the destructor too

- Pouya / FOO!!!

#define PURE_STUPIDITY 128 PROGRAMMERS

Share this post


Link to post
Share on other sites
Aha! So obvious I can''t believe I didn''t think of it! I was somehow under the impression that this should automatically occur for destructors. I use virtual all the time for other member functions, but it never occurred to me...

Thanks for the help.

Starfall

Share this post


Link to post
Share on other sites
Are you using Visual C++?

I ask, because Visual C++ doesn''t insist on destructors being virtual, whereas I (and others) are certain that the C++ spec requires that a destructor be virtual, whether or not you declare it such.

I''m interested to know if other C++ compilers, such as GCC/DJGPP, Borland, etc, do this.

Anyway, the bottom line is, /always/ declare your destructors to be virtual - not just the base class. Why?

Well, imagine this:


CObject
{
virtual ~CObject();
};

CBaseWindow : public CObject
{
~CBaseWindow();
};

CButton : public CBaseWindow
{
~CButton();
}

CObject *pButton = new CButton();
delete pButton;


Can you tell me what would happen? It''s undefined behaviour - I would expect that the CBaseWindow and CObject destructors would get called properly, but not the CButton one, because there''s no polymorphism chain explicitly declared.

This might not be what the C++ spec says, but since when do Microsoft and other obey a spec to the letter?

I think it''s despicable that Visual C++ doesn''t even generate a warning about non-virtual destructors, and that''s at ''warning level 4'' (for those that don''t know, that tells the compiler to be picky as hell).

Personally, I want my compiler to spew errors if it finds a non-virtual destructor, /or/ have an option to give a warning and then treat it as virtual anyway.

Can anyone give a good reason why it should be possible to break the polymorphism chain on destructors?

TheTwistedOne
http://www.angrycake.com

Share this post


Link to post
Share on other sites
Since you asked...
Besides speed, there are two other reasons not to make destructors virtual.
1) Size. Adding a single virtual method to a class requires the addition of a pointer to the vtable for each instance of the class. This is usually only 4 bytes, but it would double the size of a small class like this:

class point {
unsigned short x, y;
};


2) Adding a vtable pointer to a class makes it incompatable with the corresponding struct in C. If you need to pass struct data between libraries in C and C++, you have to make sure that there are no virtual methods (including destructors) on the structs.

However, I agree that the vast majority of time you DO want destructors to be virtual. It would be nice if VC flagged non-virtual destructors as errors, so long as there was a way to #pragma the error off for cases when you KNOW you want non-virtual destructors.

Share this post


Link to post
Share on other sites
Borland and Metrowerks compilers do not require virtual dtors

Such a requirement, as said before is, in fact, a violation of the C++ spec.

A dtor is virtual if declared as such or, if it inherits from a base class which has a destructor declared as virtual ( just like methods )

If you do not explicitly declare a dtor the compiler generates one for you - if your class inherits from a class with a virtual dtor then the compiler will generate a virtual dtor, otherwise it will create a non-virtual one.

Personally, I like to make sure and declare things virtual in every class in the heirarchy that they need to be. It makes things clearer when looking at one module. For example:


Module A -

class Base
{
public:

Base();
virtual ~Base();

virtual void Nothing() = 0;
};

Module B - ( a separate .cpp file )

- include Module A -

class Derived : public Base
{
private:

long iVal;

public:

Derived();
virtual ~Derived();

virtual void Nothing();
};


However, declaring all methods virtual can be overkill. Especially since virtual causes inline functions to be out-of-line when the compiler cannot determine the type at compilation time.




Edited by - SteveC on July 14, 2000 5:53:51 PM

Edited by - SteveC on July 14, 2000 5:55:13 PM

Share this post


Link to post
Share on other sites
Armitage: Speed. Hmm. Personally, I''d take predictability over performance in the case of destructors.

Syzygy: Oh. I tend to forget that a struct is a class according to C++. That''s a good reason.

SteveC: I quite agree. Regardless of what a compiler does or doesn''t do, it''s always best to write things out fully, for everybody''s sake.

I''m aware of default constructors and destructors - which is why you''d find a lot of empty ones in my classes, if you were to peek at them.

I''m not talking about functions in general, though. I fully understand that making everything virtual is a road to performance hell.

Overall, I suppose that it''s unfair to demand that the default be that destructors are virtual. The biggest argument against, I think, would be that such is the opposite of the normal behaviour.

I don''t think I''m being unreasonable in desiring compilers to tell you if you forget to make a destructor virtual, though. Even as a turned-off-by-default option.

Are you listening, Bill

TheTwistedOne
http://www.angrycake.com

Share this post


Link to post
Share on other sites
Well, I misread the question somewhat. I didn't realize that he meant "breaking" a virtual chain. I thought he wanted a reason for omitting a virtual dtor from the beginning (gave my reply in regard to the first post). If you're building a concrete class you shouldn't use virtual, imo, and I honestly don't know what happens if you start making them virtual further down the tree?

But if there is a virtual one at the top, I'd like to find out from the compiler before introducing small...features into my programs


Edited by - Armitage on July 15, 2000 6:07:38 AM

Edited by - Armitage on July 15, 2000 6:09:25 AM

Share this post


Link to post
Share on other sites