473,396 Members | 1,789 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

virtual destructors for classes only with virtual functions?

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
23 2102
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
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
Thanks for both of you!

Jul 23 '05 #4
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
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
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

"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
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
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
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

"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

"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

"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
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
> 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
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
> 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

"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
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

"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
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
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
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

39
by: Ele | last post by:
Is it correct to say that Whenever a class has a virtual member function, define its destructor as "virtual"? Can a destructor as "pure virtual"? When is it needed to do so? For an interface,...
2
by: Chunhui Han | last post by:
Hi, I was recently reading about virtual base classes in C++. The book I was reading says that it is illegal to have non-virtual destructor for the virtual base class. It seems to me that...
15
by: christopher diggins | last post by:
I posted to my blog a special pointer class work-around for inheriting from base classes without virtual destructors. I was wondering if there is any other similar work, and whether there are any...
11
by: santosh | last post by:
Hello, I was going through the Marshal Cline's C++ FAQ-Lite. I have a doubt regarding section 33.10. Here he is declaring a pure virtual destructor in the base class. And again defining...
37
by: WittyGuy | last post by:
Hi, I wonder the necessity of constructor and destructor in a Abstract Class? Is it really needed? ? Wg http://www.gotw.ca/resources/clcm.htm for info about ]
3
by: Pravesh | last post by:
Hello All, I had some query regarding virtual functions/destructors. If a class is having some/all of its methods that are virtual then is it recommended that it should also have virtual...
5
by: druberego | last post by:
I read google and tried to find the solution myself. YES I do know that you can get undefined references if you: a) forget to implement the code for a prototype/header file item, or b) you forget...
7
by: eric | last post by:
hello i'm confused by an example in the book "Effective C++ Third Edition" and would be grateful for some help. here's the code: class Person { public: Person(); virtual ~Person(); // see...
9
by: desktop | last post by:
On this page: http://www.eptacom.net/pubblicazioni/pub_eng/mdisp.html Shape specify the virtual function: virtual double Intersect( const Shape& s) = 0; then the derived class Circle...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.