473,395 Members | 1,568 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,395 software developers and data experts.

virtual destructor revisted

A reason for declaring a "virtual destructor" for a Base class is to make
sure the destructor of Derived class will be invoked when a pointer of Base
type is used to delete an object of Derived.

Is this the only reason to define "virtual destructor" for a Base class?

Since it's always possible that users of any Base class will delete a
Derived object like that, does this mean that a "virtual destructor" is
always necessary?

Thanks in advance!


Jul 22 '05 #1
23 2336
ctick wrote:
A reason for declaring a "virtual destructor" for a Base class is to make
sure the destructor of Derived class will be invoked when a pointer of Base type is used to delete an object of Derived.

Is this the only reason to define "virtual destructor" for a Base class?

Since it's always possible that users of any Base class will delete a
Derived object like that, does this mean that a "virtual destructor" is
always necessary?

Thanks in advance!


Make all destructors virtual unless profiling reveals you really really
really don't need one.

If your class is abstract, with only pure virtual methods, make the
destructor pure virtual too.

Only one sequence of events leads to undefined behavior: A base class has no
virtual destructor, you derive from it, create a 'new' derived object, take
this object's address, convert the address to the base type, and 'delete'.

'delete'ing a base type pointer is not a rare sequence of events in wildly
polymorphic designs. You should take greater care to ensure that the return
value of 'new' is always stored in a smart pointer or equivalent of the
correct derived type, so destruction becomes automatic. And plenty of
polymorphic designs use only the stack to store objects, so all these
situations destroy and clean up correctly.

However, refactors and new features could easily migrate a statically
allocated object into a dynamic one. At this time, nothing in your system
will tell you if your 'delete' creates undefined behavior (except possibly a
lint tool).

The language permits this loophole to permit tuning performance. Sometimes
the tiny overhead of a virtual method table hurts, so you can always take it
out. A keyword called "unvirtual" would be silly, so you must simply always
make destructors virtual.

--
Phlip
http://industrialxp.org/community/bi...UserInterfaces
Jul 22 '05 #2

"ctick" <ct***@flare.com> wrote in message
news:bZ*****************@bgtnsc05-news.ops.worldnet.att.net...
A reason for declaring a "virtual destructor" for a Base class is to make
sure the destructor of Derived class will be invoked when a pointer of Base type is used to delete an object of Derived.

Is this the only reason to define "virtual destructor" for a Base class?
Pretty much yes. There is one other rather obscure reason. It might be that
you want class Base to have at least one virtual function (so that you can
use dynamic_cast on it for instance) but you don't have any other suitable
method to declare as virtual.

Since it's always possible that users of any Base class will delete a
Derived object like that, does this mean that a "virtual destructor" is
always necessary?


Not really. There is an overhead to using virtual functions. If your class
is not intended to be used polymorphically then don't use any virtual
functions (including destructor) and document that fact. Unfortunately its
always possible that users will do something stupid.

john
Jul 22 '05 #3
Phlip wrote:
ctick wrote:
A reason for declaring a "virtual destructor" for a Base class
is to make sure the destructor of Derived class will be invoked
when a pointer of Base type is used to delete an object of Derived.

Is this the only reason to define "virtual destructor" for a Base class?

Since it's always possible that users of any Base class
will delete a Derived object like that, does this mean that
a "virtual destructor" is always necessary?


Make all destructors virtual
unless profiling reveals you really really really don't need one.


This is *very* bad advice.
If all C++ destuctors were meant to be virtual,
that feature would have been built into the language --
or the language would have been renamed Java.
Jul 22 '05 #4
John Harrison wrote:
There is an overhead to using virtual functions.
class Base {
public:
virtual
~Base(void) { }
};

class Derived: public Base {
public:
virtual
~Derived(void) { }
};

void blackHole(Base* p) {
delete [] p;
}

Derived* p = new Derived[bzillion];
blackHole(p);

The destructors do nothing and a good C++ compiler
could have optimized them away if they weren't virtual destructors
but, because the destuctor for the base class was declared virtual,
the compiler will be forced to emit code to call the destructor
for Derived a bzillion times -- to do nothing!
If your class is not intended to be used polymorphically,
then don't use any virtual functions (including destructor)
and document that fact.


Even if your class *is* intended to be used polymorphically,
you really need a strong argument to include a virtual destructor.
Jul 22 '05 #5
On Sat, 19 Jun 2004 22:51:01 -0700 in comp.lang.c++, "E. Robert Tisdale"
<E.**************@jpl.nasa.gov> wrote,

This is *very* bad advice.
If all C++ destuctors were meant to be virtual,
that feature would have been built into the language --
or the language would have been renamed Java.


Come on, Robert, you know it's only very ordinary everyday grade bad
advice. Sure it will make your programs slower and eat a bit more
memory for no good reason, but I can't think of a case where it will
make them give wrong answers or undefined behavior. And it might even
save somebody's clueless butt, once in a blue moon. I told you a
million times not to exaggerate.

Jul 22 '05 #6
"David Harmon" <so****@netcom.com.invalid> wrote in message
news:40***************@news.west.earthlink.net

I told you a
million times not to exaggerate.


:) :)
--
John Carson
1. To reply to email address, remove donald
2. Don't reply to email address (post here instead)
Jul 22 '05 #7
ctick posted:
A reason for declaring a "virtual destructor" for a Base class is to
make sure the destructor of Derived class will be invoked when a
pointer of Base type is used to delete an object of Derived.

Is this the only reason to define "virtual destructor" for a Base
class?

Since it's always possible that users of any Base class will delete a
Derived object like that, does this mean that a "virtual destructor" is
always necessary?

Thanks in advance!


Write your program. At the end, analyse it and see if you use a pointer of
type Base* to delete an object of type Derived . If so, declare ~Base
virtual. If not... DON'T! Very simple.
Where things get a little more complex is with reusable code. Let's say you
write a super duper special class:

class SuperDuperSpecial;
You're not guaranteed that the "user" of your class will not...(the
aformentioned).

Solution:

A) Just declare the destructor virtual.

B) Supply two forms:

class SuperDuperSpecialVirtualDestructor;
Jul 22 '05 #8
Phlip wrote in news:ph***************@newssvr33.news.prodigy.com in
comp.lang.c++:
Make all destructors virtual unless profiling reveals you really
really really don't need one.

If your class is abstract, with only pure virtual methods, make the
destructor pure virtual too.
Pointless, the only reason to make a destuctor *pure*-virtual is because
the class has no other pure-virtuals and you want the class to be
abstract.

Only one sequence of events leads to undefined behavior: A base class
has no virtual destructor, you derive from it, create a 'new' derived
object, take this object's address, convert the address to the base
type, and 'delete'.


Nonsense:

- Never use `delete`.
- `new` should only be used to initialize a smart pointer.
- `new` is nessacery in C++, but you shouldn't use it like
you would in a OO / GC language (java/C#).

Just countering your silly advice with silly advice of my own,
sensible people will ignore both of us.

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #9
E. Robert Tisdale wrote:
Phlip wrote:

Make all destructors virtual
unless profiling reveals you really really really don't need one.


This is *very* bad advice.
If all C++ destuctors were meant to be virtual,
that feature would have been built into the language --
or the language would have been renamed Java.


I covered that when I pointed out that a keyword "unvirtual" would be silly.

Read the /Effective C++/ books.

--
Phlip
Jul 22 '05 #10
David Harmon wrote:
E. Robert Tisdale wrote,

This is *very* bad advice.
If all C++ destuctors were meant to be virtual,
that feature would have been built into the language --
or the language would have been renamed Java.


Come on, Robert, you know it's only very ordinary everyday grade bad
advice. Sure it will make your programs slower and eat a bit more
memory for no good reason, but I can't think of a case where it will
make them give wrong answers or undefined behavior. And it might even
save somebody's clueless butt, once in a blue moon. I told you a
million times not to exaggerate.


How much slower?

It's a loaded question. Even figuring out how much slower spends time that
you could have used to take 'new' out of your design, which would make your
destructors early-bound.

Premature optimization is the root of all evil. Not "some" evil.

--
Phlip
http://industrialxp.org/community/bi...UserInterfaces
Jul 22 '05 #11
"Phlip" <ph*******@yahoo.com> wrote in message
news:ph***************@newssvr33.news.prodigy.com. ..
If your class is abstract, with only pure virtual methods, make the
destructor pure virtual too.


Why? This advice makes no sense to me.
Jul 22 '05 #12
Andrew Koenig wrote:
Phlip wrote:
If your class is abstract, with only pure virtual methods, make the
destructor pure virtual too.


Why? This advice makes no sense to me.


As someone pointed out, I was trying to remember an alternative advice: To
make a class abstract, if it has no pure virtual methods, make the
destructor pure virtual.

--
Phlip
http://industrialxp.org/community/bi...UserInterfaces
Jul 22 '05 #13
> As someone pointed out, I was trying to remember an alternative advice: To
make a class abstract, if it has no pure virtual methods, make the
destructor pure virtual.


If it has no pure virtual methods, why do you want to make it abstract?
Jul 22 '05 #14
Andrew Koenig posted:
As someone pointed out, I was trying to remember an alternative
advice: To make a class abstract, if it has no pure virtual methods,
make the destructor pure virtual.


If it has no pure virtual methods, why do you want to make it abstract?

I asked the exact same question a couple of months ago!

Consider a bank account. The routine for withdrawing cash and lodging cash
is the same for every single type of bank account. So there's going to be
definitions of each function. As such, there'll be no need for any virtual
functions.

There's checking accounts, there's savings accounts, there's student
accounts. But there's no such thing as just "an account". You don't want
people in your bank opening "an account":

Account my_account;
So you declare the destructor as pure virtual. Now some-one can't just open
an account:

Account my_account; //Compile error
They have to open a specific type of account:

SavingsAccount my_account; //Yipee!!
-JKop
Jul 22 '05 #15
* Andrew Koenig:
As someone pointed out, I was trying to remember an alternative advice: To
make a class abstract, if it has no pure virtual methods, make the
destructor pure virtual.


If it has no pure virtual methods, why do you want to make it abstract?


Well, three features of an abstract class are that (1) it can be
inherited from and (2) it cannot be directly instantiated and (3) it
supports polymorphism, especially RTTI, and those three features
coincide precisely with the ideal features of a marker interface.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 22 '05 #16
Alf P. Steinbach wrote:
* Andrew Koenig:
As someone pointed out, I was trying to remember an alternative advice: To make a class abstract, if it has no pure virtual methods, make the
destructor pure virtual.


If it has no pure virtual methods, why do you want to make it abstract?


Well, three features of an abstract class are that (1) it can be
inherited from and (2) it cannot be directly instantiated and (3) it
supports polymorphism, especially RTTI, and those three features
coincide precisely with the ideal features of a marker interface.


Thanks. I was going to say that when I discover the need, I'd have the
technique ready.

--
Phlip
http://industrialxp.org/community/bi...UserInterfaces
Jul 22 '05 #17
JKop wrote:
I asked the exact same question a couple of months ago!

Consider a bank account. The routine for withdrawing cash and lodging cash
is the same for every single type of bank account. So there's going to be
definitions of each function. As such, there'll be no need for any virtual
functions.

There's checking accounts, there's savings accounts, there's student
accounts. But there's no such thing as just "an account". You don't want
people in your bank opening "an account":

Account my_account;
So you declare the destructor as pure virtual. Now some-one can't just open an account:

Account my_account; //Compile error
They have to open a specific type of account:

SavingsAccount my_account; //Yipee!!


With any virtual method in that system, it's the Abstract Template Design
Pattern. Without, it's a compilable comment.

Either Savings and Checking are attributes of a concrete Account, or some
Account routine varies its internal features polymorphically. Even then, an
Account could store a reference to an abstract AccountType, which
specializes only the behaviors for Savings and Checking.

Don't inherit without overwhelming need. Prefer delegation where possible.

--
Phlip
http://industrialxp.org/community/bi...UserInterfaces
Jul 22 '05 #18
"Alf P. Steinbach" <al***@start.no> wrote...
* Andrew Koenig:
As someone pointed out, I was trying to remember an alternative advice: To make a class abstract, if it has no pure virtual methods, make the
destructor pure virtual.


If it has no pure virtual methods, why do you want to make it abstract?


Well, three features of an abstract class are that (1) it can be
inherited from and (2) it cannot be directly instantiated and (3) it
supports polymorphism, especially RTTI, and those three features
coincide precisely with the ideal features of a marker interface.


Wouldn't it be easier to make its constructor protected instead?
Jul 22 '05 #19
* Victor Bazarov:
"Alf P. Steinbach" <al***@start.no> wrote...
* Andrew Koenig:
> As someone pointed out, I was trying to remember an alternative advice: To > make a class abstract, if it has no pure virtual methods, make the
> destructor pure virtual.

If it has no pure virtual methods, why do you want to make it abstract?


Well, three features of an abstract class are that (1) it can be
inherited from and (2) it cannot be directly instantiated and (3) it
supports polymorphism, especially RTTI, and those three features
coincide precisely with the ideal features of a marker interface.


Wouldn't it be easier to make its constructor protected instead?


Then you lose feature (3).

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 22 '05 #20
* Alf P. Steinbach:
* Victor Bazarov:
"Alf P. Steinbach" <al***@start.no> wrote...
* Andrew Koenig:
> > As someone pointed out, I was trying to remember an alternative

advice: To
> > make a class abstract, if it has no pure virtual methods, make the
> > destructor pure virtual.
>
> If it has no pure virtual methods, why do you want to make it abstract?

Well, three features of an abstract class are that (1) it can be
inherited from and (2) it cannot be directly instantiated and (3) it
supports polymorphism, especially RTTI, and those three features
coincide precisely with the ideal features of a marker interface.


Wouldn't it be easier to make its constructor protected instead?


Then you lose feature (3).


Bang! Bang! He knew that if he ever let wind in the echo chamber, he
would never hear the end of it...

Sorry, you don't lose feature (3), unless the destructor is non-virtual
(which is what I read in addition to what you actually wrote).

Easier, perhaps, but "= 0" conveys the abstractness very directly.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 22 '05 #21
On Sun, 20 Jun 2004 13:00:20 GMT in comp.lang.c++, "Phlip"
<ph*******@yahoo.com> wrote,
How much slower?


An amount that is usually, but not always, insignificant.
Otherwise I would be agreeing with Robert. But it's not really the
speed, it's writing code that you don't need and that complicates your
application. It smells. Don't add "virtual" to anything unless it
serves a _current_ purpose. You aren't going to need it.

Jul 22 '05 #22
David Harmon wrote:
E. Robert Tisdale wrote,
This is *very* bad advice.
If all C++ destuctors were meant to be virtual,
that feature would have been built into the language --
or the language would have been renamed Java.
Come on, Robert,
you know it's only very ordinary everyday grade bad advice.
Sure it will make your programs slower and eat a bit more memory
for no good reason, but I can't think of a case
where it will make them give wrong answers or undefined behavior.
And it might even save somebody's clueless butt,
once in a blue moon.


These are actually very good reasons
for the trade-off that Java (and Smalltalk) make
in sacrificing a little performance and efficiency
to make the language a little simpler and safer.
This is a big win for 90% of all applications
but unacceptable for some high performance applications.
C++ is a little more complicated.
It allows (and requires) the programmer to exercise
more options that can result in code
that is faster and more efficient.
I told you a million times not to exaggerate.

Jul 22 '05 #23
David Harmon wrote:
Phlip wrote,

How much slower?


An amount that is usually, but not always, insignificant.
Otherwise I would be agreeing with Robert. But it's not really the
speed, it's writing code that you don't need and that complicates your
application. It smells. Don't add "virtual" to anything unless it
serves a _current_ purpose. You aren't going to need it.


The Simplicity Principles:

After adding each tiny ability, run this checklist, in order, and refactor
until your code:

0. Obeys your team's Sane Subset and style guidelines
1. Passes All Tests
2. Expresses Intent Clearly
3. Duplicates No Behavior
4. Minimizes Classes, Methods, and Statements.

Repeat those checks, throughout a project's lifecycle, to keep it simple but
understandable at all times. Apply them in order-don't remove that last bit
of duplication if the result wouldn't express intent clearly. Some languages
enable more obfuscation than others do. At least put duplicated things next
to each other.

Doing things your compiler cannot do for you, such as smart pointers,
private unimplemented copy operations, virtual destructors, etc, are at
level 0. You cannot test them into place, or use them to improve expression.
"Design Smells" start at level 2, after the code works.

A team using C++ must maintain awareness of a common Sane Subset. This
includes things like whether colleagues would have provided virtual
destructors, or whether you must go looking for them when you attempt to
polymorph.

--
Phlip
http://industrialxp.org/community/bi...UserInterfaces
Jul 22 '05 #24

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

11
by: Stub | last post by:
Please answer my questions below - thanks! 1. Why "Derived constructor" is called but "Derived destructor" not in Case 1 since object B is new'ed from Derived class? 2. Why "Derived destructor"...
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,...
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 ]
4
by: Tony Johansson | last post by:
Hello Experts!! Assume I have a base class called animal. I want this class to be abstract so I make the destructor pure virtual by having this statement. virtual ~Animal() = 0; Destructor...
26
by: pmizzi | last post by:
When i compile my program with the -ansi -Wall -pedantic flags, i get this warning: `class vechile' has virtual functions but non-virtual destructor, and the same with my sub-classes. But when i...
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...
7
by: sam | last post by:
Hi, See when i reading a sourcecode of a program, I read that the constructor is ordinary and after that the programmer has written virtual destructor for that constructor . Why we use the...
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...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
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
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

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.