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! 23 2261
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
"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
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.
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.
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.
"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)
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;
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/
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
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
"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.
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
> 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?
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
* 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?
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
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
"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?
* 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?
* 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?
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.
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.
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 This discussion thread is closed Replies have been disabled for this discussion. Similar topics
11 posts
views
Thread by Stub |
last post: by
|
39 posts
views
Thread by Ele |
last post: by
|
11 posts
views
Thread by santosh |
last post: by
|
37 posts
views
Thread by WittyGuy |
last post: by
|
4 posts
views
Thread by Tony Johansson |
last post: by
|
26 posts
views
Thread by pmizzi |
last post: by
|
7 posts
views
Thread by eric |
last post: by
|
7 posts
views
Thread by sam |
last post: by
| | | | | | | | | | |