By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,107 Members | 1,173 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,107 IT Pros & Developers. It's quick & easy.

virtual destructors for classes only with virtual functions?

P: n/a
Hi,

Most of the books on C++ say something like this: "A virtual destructor
should be defined if the class contains at least one virtual member
function."

My question is: why is it only for the case when the class contains at
least one virtual member function? Shouldn't the destructor always be
virtual, whenever there's a possibility that an inherited object will
be destructed through a base class pointer? (This does not require,
that the base class have any other virtual function!)

Thanks!

ps: can someone please explain me briefly, why a concrete base class
cannot have an abstract derived class?

Jul 23 '05 #1
Share this Question
Share on Google+
23 Replies


P: n/a
heted7 wrote:
My question is: why is it only for the case when the class contains at
least one virtual member function? Shouldn't the destructor always be
virtual, whenever there's a possibility that an inherited object will
be destructed through a base class pointer? (This does not require,
that the base class have any other virtual function!)


Because it will be uncommon that you wants to destroy polimorphically
objetcts that are not used polimorphically, and the majority of the books
talks about more common cases. And to add it to class in this case has some
overhead and many people does not want to pay this price.

But if you have reasons to add a virtual destructor, do it. The books says
that in that case you must add it, not that you must not do it in any other
case.

--
Salu2
Jul 23 '05 #2

P: n/a
Julián Albo wrote:

But if you have reasons to add a virtual destructor, do it. The books says
that in that case you must add it, not that you must not do it in any other
case.


And, just as not saying there are other cases where you need it is an
oversimplification, saying that you always need it when you have virtual
functions is an oversimplification.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 23 '05 #3

P: n/a
Thanks for both of you!

Jul 23 '05 #4

P: n/a
Pete Becker wrote:
saying that you always need it when you have virtual
functions is an oversimplification.


An example, please!

::A::

Jul 23 '05 #5

P: n/a
heted7 wrote:
Most of the books on C++ say something like this,
"A virtual destructor should be defined
if the class contains at least one virtual member function."
This is generally bad advice. Ignore it.
My question is, "Why is it only for the case
when the class contains at least one virtual member function?"
Shouldn't the destructor always be virtual whenever there's a possibility
that an inherited object will be destructed through a base class pointer?
(This does not require, that the base class have any other virtual function!)


Don't define a virtual destructor unless you have a specific use for it.
Generally, C++ functions shouldn't be destroying objects passed to them
by reference (or by reference through a pointer).
Jul 23 '05 #6

P: n/a
heted7 wrote:
Most of the books on C++ say something like this: "A virtual destructor should be defined if the class contains at least one virtual member
function."


This is generally a good rule of thumb. Don't ignore it.
See also: http://www.artima.com/cppsource/bigtwo.html

::A::

Jul 23 '05 #7

P: n/a

"E. Robert Tisdale" <E.**************@jpl.nasa.gov> skrev i en meddelelse
news:d5**********@nntp1.jpl.nasa.gov...
heted7 wrote:
Most of the books on C++ say something like this,
"A virtual destructor should be defined
if the class contains at least one virtual member function."
This is generally bad advice. Ignore it.
My question is, "Why is it only for the case
when the class contains at least one virtual member function?"
Shouldn't the destructor always be virtual whenever there's a
possibility
that an inherited object will be destructed through a base class pointer?
(This does not require, that the base class have any other virtual
function!)

That's simply not true. The destructor SHOULD be virtual unless you have a
compelling reason for it not being so. The only compelling reason i can
think of would be performance-related. So unless you profile your code and
decide that the overhead of the virtual function is excessive (and with a
good compiler, there should be no overhead if the type is statically known),
do keep that destructor virtual.
Don't define a virtual destructor unless you have a specific use for it.
Generally, C++ functions shouldn't be destroying objects passed to them
by reference (or by reference through a pointer).

Also I recommend that if you have a class with virtual functions and no
virtual destructor, you sohuld remove the new-operator for that class. If
the class is meant to be used by others, this is nearly a must.

/Peter
Jul 23 '05 #8

P: n/a
Peter Koch Larsen wrote:
The destructor SHOULD be virtual
unless you have a compelling reason for it not being so.


Why?
Jul 23 '05 #9

P: n/a
E. Robert Tisdale wrote:
Peter Koch Larsen wrote:
The destructor SHOULD be virtual
unless you have a compelling reason for it not being so.

Why?


To increase code bloat, of course.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 23 '05 #10

P: n/a
Pete Becker wrote:
E. Robert Tisdale wrote:
Peter Koch Larsen wrote:
The destructor SHOULD be virtual
unless you have a compelling reason for it not being so.


Why?


To increase code bloat, of course.


It was a "straight-up" question.
Jul 23 '05 #11

P: n/a

"E. Robert Tisdale" <E.**************@jpl.nasa.gov> skrev i en meddelelse
news:d5**********@nntp1.jpl.nasa.gov...
Peter Koch Larsen wrote:
The destructor SHOULD be virtual
unless you have a compelling reason for it not being so.


Why?


When you create a class with a virtual function, by definition you are going
to use that class in a polymorphic way. In that case it is reasonable to
expect some user of that class to delete an object derived from that class
by calling the destructor with only access to your base-class. You might not
anticipate any such need, but having a virtual destructor enables that
feature. So lets have a look at the cost.
A virtual destructor is expensive in a class that does not already have
virtual functions: the vtable entry incurs an extra cost for every object
created. If you already have a virtual function this cost disappears, so the
added storage cost becomes practically zero. As for runtime costs, there
should not be any overhead either. The compiler will not have to call the
destructor using the vtable when the type of the object is statically known.
All in all it thus looks that all you save is one entry in the V-table,
which is something on the order of four to eight bytes. That is not per
object but for the entire program.
Thus the virtual destructor comes almost free in your case, and - as i
stated in my previous post - unless you have some compelling reason not to
make the destructor virtual you should let it be virtual.

/Peter
Jul 23 '05 #12

P: n/a

"Pete Becker" <pe********@acm.org> skrev i en meddelelse
news:6u********************@giganews.com...
Peter Koch Larsen wrote:

If you read my post again, you will see that your argument does not hold
water. I specifically made a distinction between classes with virtual
functions and classes without. By having a virtual function you state
that your class is to be used polymorphically, and then the specific
advice - have a virtual destructor unless you have good arguments that it
should not be so - holds.
If you read my post again, you will see that your argument does not hold
water. I specifically said that the reason for having a virtual destructor
is that your design calls for deleting objects of derived types through
pointers to the base. That is not the same as having or not having other
virtual functions, nor does it have anything to do with being "used
polymorhpically."


Surely we agree on that item: virtual destructors are for deleting derived
objects via a base-pointer, and not anything else. Still, if i saw code with
a virtual function but no virtual destructor i would be suspicious. I have
yet to see a class where there has been a virtual function without a virtual
destructor or some means for prohibiting a direct "new".

/Peter
--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)

Jul 23 '05 #13

P: n/a

"E. Robert Tisdale" <E.**************@jpl.nasa.gov> skrev i en meddelelse
news:d5**********@nntp1.jpl.nasa.gov...
Peter Koch Larsen wrote:
E. Robert Tisdale wrote:
Peter Koch Larsen wrote:

The destructor SHOULD be virtual
unless you have a compelling reason for it not being so.

Why?
When you create a class with a virtual function,
by definition you are going to use that class in a polymorphic way.


I have no idea what you mean by that.

Isn't the only reason for a virtual function that the object is intended to
be derived from and to be used polymorphically?
In that case, it is reasonable to expect some user of that class
to delete an object derived from that class by calling the destructor
with only access to your base-class.
You might not anticipate any such need
but having a virtual destructor enables that feature.
Generally, it's a bad idea to have functions delete objects
passed to them by reference (or by reference through a pointer):


I do not know how the object is to be deleted. Someone did new it (since my
advice to "hide" operator new wasn't followed), and thus it should be
deleted somehow. If it is via a plain delete or some smart pointer, I don't
know, but since it was newed, I assume it can not happen at the place of
construction (no reason to use new).

[snip]
So let's have a look at the cost. A virtual destructor is expensive
in a class that does not already have virtual functions:
the vtable entry incurs an extra cost for every object created.
If you already have a virtual function this cost disappears
so the added storage cost becomes practically zero.
As for runtime costs, there should not be any overhead either.
The compiler will not have to call the destructor using the vtable
when the type of the object is statically known.
Have you actually tested this?

[snop example]
How do I get my GNU C++ compiler to optimize away
the virtual destructor call in this case? I don't know. What I know is that a static call to the known destructor
would be fine in the example you gave. And if you read my original post, you
will notice that if the call of the virtual destructor turns out to be to
expensive, I see apn excuse to remove the destructor in that particular
case. This is an inconvenience for the user of the class however, and i
recommend instead that the new operator should be made private (come to
think of it, removing "delete" is far superior as it only requires a
"destroy" function).
All in all, it thus looks that all you save is one entry in the V-table
which is something on the order of four to eight bytes.
That is not per object but for the entire rogram.
Thus the virtual destructor comes almost free in your case
and - as i stated in my previous post -
unless you have some compelling reason
not to make the destructor virtual you should let it be virtual.
It doesn't make any sense to make a destructor a virtual function
unless you actually write code that *must* use it that way.


I see it this way:
It doesn't make any sense to make a destructor a virtual function
unless you actually write code that *might* use it that way. I call it
"defensive" programming.
If someone else needs a virtual destructor,
they can always derive a new base class from your base class
that *has* a virtual destructor
and use it to define their new functions instead. They sure can.


/Peter
Jul 23 '05 #14

P: n/a
Peter Koch Larsen wrote:
I have
yet to see a class where there has been a virtual function without a virtual
destructor or some means for prohibiting a direct "new".


"There are more things in heaven and Earth, Horatio, than are dreamt of
in your philosophy."

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 23 '05 #15

P: n/a
> Surely we agree on that item: virtual destructors are for deleting derived
objects via a base-pointer, and not anything else. Still, if i saw code
with a virtual function but no virtual destructor i would be suspicious. I
have yet to see a class where there has been a virtual function without a
virtual destructor or some means for prohibiting a direct "new".

/Peter


I just happen to be working on such a class now. It's simply an abstract
base class providing an interface so I can store a list of derived objects
and call a few functions on them. I may even add some data members if
necessary.

class IVolatileResource
{
public:
virtual void OnResourceLost()=0;
virtual void OnResourceRestore()=0;
};

No-one is ever intended, nor do I predict a use for, deleting via an
IVolatileResource*. Yet now all classes implementing this interface have
virtual functions. Should they all now have a virtual destructor? Should
IVolatileResource have one? IMO they don't (the derived classes may for some
other reason). Alternatively, should 'new' be disabled? What is
IVolatileResource to dictate such terms to derived classes?

Anyway, just thought I'd join in with an example of where I consider virtual
destructors unnecessary. For a base type that provides more useful
functionality and thus more likely to be kept as that type I would agree and
suggest that a virtual destructor be seriously considered.

Regard,
cadull
Jul 23 '05 #16

P: n/a
Peter Koch Larsen wrote:
E. Robert Tisdale wrote:
Peter Koch Larsen wrote:
E. Robert Tisdale wrote:

Peter Koch Larsen wrote:

>The destructor SHOULD be virtual
>unless you have a compelling reason for it not being so.

Why?

When you create a class with a virtual function,
by definition you are going to use that class in a polymorphic way.
I have no idea what you mean by that.


Isn't the only reason for a virtual function that
the object is intended to be derived from and to be used polymorphically?


Are you claiming that
an object which does not "have" a virtual destructor
cannot be used polymorphically?
If so, you really need to elaborate on your notion of polymorphism.
In that case, it is reasonable to expect some user of that class
to delete an object derived from that class by calling the destructor
with only access to your base-class.
You might not anticipate any such need
but having a virtual destructor enables that feature.
Generally, it's a bad idea to have functions delete objects
passed to them by reference (or by reference through a pointer):


I do not know how the object is to be deleted.
Someone did new it (since my advice to "hide" operator new wasn't followed)
and thus it should be deleted somehow.
If it is via a plain delete or some smart pointer,
I don't know but, since it was new'd,
I assume it can not happen at the place of construction (no reason to use new).


I have no idea what you are talking about here.
Evidently, you are *not* talking about my example:

void f(const X* p) {
delete p;
}

int main(int argc, char* argv[]) {
X x(13);
f(&x);
std::cout << "x = " << x << std::endl;
return 0;
}

which you snipped.
[snip]

Maybe you could provide an example which shows what you mean.
So let's have a look at the cost. A virtual destructor is expensive
in a class that does not already have virtual functions:
the vtable entry incurs an extra cost for every object created.
If you already have a virtual function this cost disappears
so the added storage cost becomes practically zero.
As for runtime costs, there should not be any overhead either.
The compiler will not have to call the destructor using the vtable
when the type of the object is statically known.


Have you actually tested this?


[snip example]
How do I get my GNU C++ compiler to optimize away
the virtual destructor call in this case?


I don't know. What I know is that a static call to the known destructor
would be fine in the example you gave.
And, if you read my original post, you will notice that,
if the call of the virtual destructor turns out to be to expensive,
I see an excuse to remove the destructor in that particular case.
This is an inconvenience for the user of the class however
and I recommend instead that the new operator should be made private
(come to think of it, removing "delete" is far superior
as it only requires a "destroy" function).
All in all, it thus looks that all you save is one entry in the V-table
which is something on the order of four to eight bytes.
That is not per object but for the entire rogram.
Thus the virtual destructor comes almost free in your case
and - as i stated in my previous post -
unless you have some compelling reason
not to make the destructor virtual you should let it be virtual.


It doesn't make any sense to make a destructor a virtual function
unless you actually write code that *must* use it that way.


I see it this way:
It doesn't make any sense to make a destructor a virtual function
unless you actually write code that *might* use it that way.


Can you give us an example of code
that *needs* to use a virtual destructor?
I call it "defensive" programming.
If someone else needs a virtual destructor,
they can always derive a new base class from your base class
that *has* a virtual destructor
and use it to define their new functions instead.


They sure can.


When superstitious people spill salt,
they still throw a pinch over their shoulder to ward off bad luck.
I'm not sure how the practice got started but I'm pretty sure that
this virtual destructor thing is a modern example.
You suggest a hypothetical case
where "someone else needs a virtual destructor"
but you haven't shown us an example of such a case.
Situations where you might employ a virtual destructor
seem to require a "virtual constructor" as well.

You main argument for virtual destructors seems to be that
they don't hurt very much.
Jul 23 '05 #17

P: n/a
> Still, if i saw code with a virtual function but no virtual destructor i
would be suspicious.


You are mistaken.
What you say is true _ONLY IF_ the class is publically inherited.
The class could be inherited privately (or protectedly) and at that point
there is no need for a virtual destructor.
And these days there are quite few advocates for private inheritance.

Stephen Howe
Jul 23 '05 #18

P: n/a

"E. Robert Tisdale" <E.**************@jpl.nasa.gov> skrev i en meddelelse
news:d5**********@nntp1.jpl.nasa.gov...
Peter Koch Larsen wrote:
E. Robert Tisdale wrote:
Peter Koch Larsen wrote:

E. Robert Tisdale wrote:

>Peter Koch Larsen wrote:
>
>>The destructor SHOULD be virtual
>>unless you have a compelling reason for it not being so.
>
>Why?

When you create a class with a virtual function,
by definition you are going to use that class in a polymorphic way.

I have no idea what you mean by that.
Isn't the only reason for a virtual function that
the object is intended to be derived from and to be used polymorphically?


Are you claiming that
an object which does not "have" a virtual destructor
cannot be used polymorphically?
If so, you really need to elaborate on your notion of polymorphism.


This thread is a consequence of your original reply:

[original poster]
"A virtual destructor should be defined
if the class contains at least one virtual member function."

[robert e. tisdale]This is generally bad advice. Ignore it.


So - obviously we are talking about "guidelines" here - not absolutes. In
those terms, polymorphic classes should NORMALLY have a virtual destructor,
and if they do not, you should either hide new and/or delete.

/Peter
Jul 23 '05 #19

P: n/a
Peter Koch Larsen wrote:
So - obviously we are talking about "guidelines" here - not absolutes.
In those terms, polymorphic classes should NORMALLY have a virtual destructor,
and if they do not, you should either hide new and/or delete.


I still don't understand why you need to hide new and/or delete.
Could you elaborate a little?
Jul 23 '05 #20

P: n/a

"E. Robert Tisdale" <E.**************@jpl.nasa.gov> skrev i en meddelelse
news:d5**********@nntp1.jpl.nasa.gov...
Peter Koch Larsen wrote:
So - obviously we are talking about "guidelines" here - not absolutes.
In those terms, polymorphic classes should NORMALLY have a virtual
destructor, and if they do not, you should either hide new and/or delete.


I still don't understand why you need to hide new and/or delete.
Could you elaborate a little?


I intended to avoid the scenario

base* b = new derived(...);
delete b; //oops - cant do with non-virtual destructor.

which a careless programmer might do - considering the "polymorphic" nature
of the base-class.
Requiring the user to write b->destroy() or something like that might
wake-up the programmer.
Of course, one could argue that proper documentation is adequate, but if i
were to make the class public (not just for in-house use), it could be
argued that my approach is somewhat more userfriendly.

/Peter
Jul 23 '05 #21

P: n/a
Peter Koch Larsen wrote:
it could be
argued that my approach is somewhat more userfriendly.


It could also be argued that it is somewhat more user unfriendly,
because users who know what they're doing have to work around your
obstruction by writing an operator new for their derived class. Don't
try to force me to write code according to your guidelines. You don't
know enough about what I'm doing.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 23 '05 #22

P: n/a
Pete Becker wrote:
Peter Koch Larsen wrote:
it could be argued that my approach is somewhat more user friendly.


It could also be argued that it is somewhat more user unfriendly,
because users who know what they're doing have to work around your
obstruction by writing an operator new for their derived class.
Don't try to force me to write code according to your guidelines.
You don't know enough about what I'm doing.


I agree. Larsen's approach is miguided.
Jul 23 '05 #23

P: n/a
Pete Becker (pe********@acm.org) wrote:
: It could also be argued that it is somewhat more user unfriendly,
: because users who know what they're doing have to work around your
: obstruction by writing an operator new for their derived class.

If I have understood correctly, this is in response to Mr. Larsen's
suggestion of making operator new private and providing a destroy()
function. What about if instead you make operator new protected?

(I'm not recommending this, I'm just enquiring.)

Jul 23 '05 #24

This discussion thread is closed

Replies have been disabled for this discussion.