C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Requirements for virtual destructors
Goto page 1, 2  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Michael
Guest





PostPosted: Thu Apr 15, 2004 12:54 am    Post subject: Requirements for virtual destructors Reply with quote





Hi all

After having initially put virtual destructors in _all_ classes that get
derived from, due to the dire warnings from the respected references about
the consequences of not doing so, I am now trying to get a bit more
sophisticated about it.

First rule I read along these lines was that a class only needs a virtual
destructor if it has at least one virtual function - is that agreed here?
How about if it doesn't have any virtual functions but is itself derived
from? More generally, how about if it's in the middle of a hierarchy with
all sorts of concrete and abstract classes above and below it, some of which
have their own virtual destructors?

Then I started thinking about when you would get caught out in other cases -
would it only be when you have explicitly used new & delete within your
class hierarchy somewhere? I am saying this because I assume that non-heap
variables manage their own destruction. How about when your hierarchy uses
containers from the standard library? I expect them to manage their own
destruction like built-in types.

If virtual destructors are only required when the hierarchy contains
explicit new/delete usage, then do smart pointers remove the need for
virtual destructors? If so, are there any reliability/speed recommendations
for the implementation of those smart pointers (I'm mainly aware of Boost &
Loki).

Apologies for the lack of clarity here - still climbing that famously steep
C++ learning curve! ;o)

Michael


_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

_/ _/ _/_/_/ Hopkins Research Limited
_/ _/ _/ _/
_/_/_/_/ _/_/_/ Optimal Solutions via Virtual Systems
_/ _/ _/ _/
_/ _/ _/ _/ Tel: +44(0) 781 3467 381

_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

`All models are wrong, but some are useful' - George Box




-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
-----== Over 100,000 Newsgroups - 19 Different Servers! =-----

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Maxim Yegorushkin
Guest





PostPosted: Fri Apr 16, 2004 6:07 am    Post subject: Re: Requirements for virtual destructors Reply with quote



Michael wrote:

[]

Quote:
First rule I read along these lines was that a class only needs a virtual
destructor if it has at least one virtual function - is that agreed here?

No.

Quote:
How about if it doesn't have any virtual functions but is itself derived
from? More generally, how about if it's in the middle of a hierarchy with
all sorts of concrete and abstract classes above and below it, some of which
have their own virtual destructors?

Virtual destructors are needed for base classes only when you want to delete your derived class object through a pointer to the base class.

--
Maxim Yegorushkin
MetaCommunications Engineering
http://www.meta-comm.com/engineering/

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
sashan
Guest





PostPosted: Fri Apr 16, 2004 6:11 am    Post subject: Re: Requirements for virtual destructors Reply with quote




Quote:
First rule I read along these lines was that a class only needs a virtual
destructor if it has at least one virtual function - is that agreed here?

A class needs at least one virtual function if it can exhibit runtime
polymorphic behaviour. So yes, if there is at least one virtual function
in the class, then there should be a virtual destructor.


Quote:
How about if it doesn't have any virtual functions but is itself derived
from?

If there are no virtual functions and it is derived from then it's safe
for it not to have a virtual destructor because it can't have any
runtime polymorphic behaviour.

More generally, how about if it's in the middle of a hierarchy with
Quote:
all sorts of concrete and abstract classes above and below it, some of which
have their own virtual destructors?


Once a member function is declared virtual any derived class that
overloads that member function is also virtual. The virtual specifier is
not needed. See 10.3 of the standard. For example this:
class Base
{
virtual void f();
};

class Derv :
public Base
{
virtual void f();
};

is the same as

class Base
{
virtual void f();
};

class Derv :
public Base
{
void f();
};

I think that should help answer the question.

Quote:
Then I started thinking about when you would get caught out in other cases -
would it only be when you have explicitly used new & delete within your
class hierarchy somewhere? I am saying this because I assume that non-heap
variables manage their own destruction. How about when your hierarchy uses
containers from the standard library? I expect them to manage their own
destruction like built-in types.


I'm confused. I'm not sure how new/delete being used by a class relates
to whether its destructor should be virtual or not.

Quote:
If virtual destructors are only required when the hierarchy contains
explicit new/delete usage, then do smart pointers remove the need for
virtual destructors?

No - I don't think so.

Quote:

Apologies for the lack of clarity here - still climbing that famously steep
C++ learning curve! ;o)


Yeah - me to. The difficulty climbing it seems to get exponentially
harder and the reward/effort ratio decreases. Sigh.

--
sashan
http://www.cs.auckland.ac.nz/~sgov008/
Public Key: http://www.keyserver.net/en/ (search for key id 0x63B4EBF5)


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Ulrich Eckhardt
Guest





PostPosted: Fri Apr 16, 2004 6:13 am    Post subject: Re: Requirements for virtual destructors Reply with quote

Michael wrote:
Quote:
After having initially put virtual destructors in _all_ classes that get
derived from, due to the dire warnings from the respected references
about the consequences of not doing so, I am now trying to get a bit more
sophisticated about it.

First rule I read along these lines was that a class only needs a virtual
destructor if it has at least one virtual function - is that agreed here?

No. I could rant about why and when for a while, but basically someone
already did it better that I probably could:
http://gotw.ca/publications/mill18.htm

Quote:
How about when your hierarchy uses containers from the standard library?
I expect them to manage their own destruction like built-in types.

How does that play in here? std-containers as members are objects like all
others. They're not suitable for public derivation, they don't have any
virtual functions anyways. Else, you can't create std::container<base>,
because of 'slicing'.

Quote:
If virtual destructors are only required when the hierarchy contains
explicit new/delete usage, then do smart pointers remove the need for
virtual destructors?

Boost's shared_ptr<> does. The first such pointer to gain ownership of an
object remembers the type of the object(unless it is already lost in
passing it to the pointer) and gives that knowledge to other pointers it
is being assigned to. That's why a shared_ptr<void> works and properly
calls the right dtor.

hth

Uli

--
Questions ?
see C++-FAQ Lite: http://parashift.com/c++-faq-lite/ first !


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
llewelly
Guest





PostPosted: Fri Apr 16, 2004 6:15 am    Post subject: Re: Requirements for virtual destructors Reply with quote

Michael <mwh_acs (AT) hotmail (DOT) com> writes:

Quote:
Hi all

After having initially put virtual destructors in _all_ classes that get
derived from, due to the dire warnings from the respected references about
the consequences of not doing so, I am now trying to get a bit more
sophisticated about it.

First rule I read along these lines was that a class only needs a virtual
destructor if it has at least one virtual function - is that agreed here?
How about if it doesn't have any virtual functions but is itself derived
from? More generally, how about if it's in the middle of a hierarchy with
all sorts of concrete and abstract classes above and below it, some of which
have their own virtual destructors?

Then I started thinking about when you would get caught out in other cases -
would it only be when you have explicitly used new & delete within your
class hierarchy somewhere? I am saying this because I assume that non-heap
variables manage their own destruction. How about when your hierarchy uses
containers from the standard library? I expect them to manage their own
destruction like built-in types.

If virtual destructors are only required when the hierarchy contains
explicit new/delete usage, then do smart pointers remove the need for
virtual destructors? If so, are there any reliability/speed recommendations
for the implementation of those smart pointers (I'm mainly aware of Boost &
Loki).
[snip]


I think if any call to the destructor would be bound differently if
the destructor were virtual, then the destructor should be made
virtual.

If a smart pointer supports polymorphism, assume a virtual destructor
is required unless the documentation says otherwise. I think for
the case of boost::shared_ptr, this usage:

boost::shared_ptr<Base> p(new Derived);

requires a virtual destructor, while:

boost::shared_ptr<Derived> p(new Derived);

does not.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
kanze@gabi-soft.fr
Guest





PostPosted: Fri Apr 16, 2004 6:15 am    Post subject: Re: Requirements for virtual destructors Reply with quote

Michael <mwh_acs (AT) hotmail (DOT) com> wrote


Quote:
After having initially put virtual destructors in _all_ classes that
get derived from, due to the dire warnings from the respected
references about the consequences of not doing so, I am now trying to
get a bit more sophisticated about it.

First rule I read along these lines was that a class only needs a
virtual destructor if it has at least one virtual function - is that
agreed here?

Its not so much a question of whether it needs it or not. Adding the
first virtual function is a cost, adding another is a much lower cost.
Making the destructor virtual if there is already a virtual function is
very, very cheap, so why not, rather than lose time asking questions
about it?

The actual rule is, of course, you need a virtual destructor if and only
if the object will be deleted through a pointer to the base class. It's
an awkward rule, in a way, because it depends on how the class is used.
Of course, if the class is used in a way it wasn't designed to be used,
then its not going to work, virtual destructor or no. But the default
assumption when a class is designed to be derived from is that I can
delete it through a pointer to the base class. If this is not true,
then normally, this fact must be documented. There are, or course,
cases where it is so obvious that this isn't the intent, std::iterator,
for example, but what is obvious to the class designer isn't necessarily
obvious to user, so unless you document it explicitly...

Globally, I like Herb Sutter's rule: if a class is designed to be used
as a base class, it either has a virtual destructor, or the destructor
is protected, so you cannot (except in a derived class) delete through a
pointer to the base class. I suspect that there are probably exceptions
to it, but I can't think of any cases where it wouldn't make sense off
hand.

Quote:
How about if it doesn't have any virtual functions but is itself
derived from? More generally, how about if it's in the middle of a
hierarchy with all sorts of concrete and abstract classes above and
below it, some of which have their own virtual destructors?

As soon as a base class has a virtual destructor, all classes which
derive from it have virtual destructors. You can't take away
virtuality.

Quote:
Then I started thinking about when you would get caught out in other
cases - would it only be when you have explicitly used new & delete
within your class hierarchy somewhere? I am saying this because I
assume that non-heap variables manage their own destruction.

The compiler knows the true type of a non-heap variable when it
generates the call to the destructor, so there is no problem.

Quote:
How about when your hierarchy uses containers from the standard
library? I expect them to manage their own destruction like built-in
types.

They do. Also like built-in types, their "destructor" isn't virtual.
They're not designed to be used as base classes.

Quote:
If virtual destructors are only required when the hierarchy contains
explicit new/delete usage, then do smart pointers remove the need for
virtual destructors?

Only if the implementation of the smart pointers never calls delete on a
pointer to the base type. All of the smart pointers I've used do call
delete on a pointer to their instantiation type -- if you instantiate
them for Base, and initialize them with a Derived*, then Base needs a
virtual destructor.

Quote:
If so, are there any reliability/speed recommendations for the
implementation of those smart pointers (I'm mainly aware of Boost &
Loki).

Boost has a means of providing your own destruction function, which
could presumably know the most derived type, even if the pointer is to
the base. If you use this, then you can probably eschew virtual
destructors. IMHO, except perhaps for some special cases, it seems
easier just to provide a virtual destructor, and let the default
destruction do its job normally.

--
James Kanze GABI Software mailto:kanze (AT) gabi-soft (DOT) fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Michiel Salters
Guest





PostPosted: Fri Apr 16, 2004 6:16 am    Post subject: Re: Requirements for virtual destructors Reply with quote

Michael <mwh_acs (AT) hotmail (DOT) com> wrote

Quote:
Hi all

After having initially put virtual destructors in _all_ classes that get
derived from, due to the dire warnings from the respected references about
the consequences of not doing so, I am now trying to get a bit more
sophisticated about it.

First rule I read along these lines was that a class only needs a virtual
destructor if it has at least one virtual function - is that agreed here?
How about if it doesn't have any virtual functions but is itself derived
from? More generally, how about if it's in the middle of a hierarchy with
all sorts of concrete and abstract classes above and below it, some of which
have their own virtual destructors?

I don't even agree with this first rule. However, the inverse is almost
always true: If a class has at least one virtual function, it probably
needs a virtual destructor. It is never wrong to make this dtor virtual,
so a safe bet is to ignore the 'probably'.

In addition, a dtor is virtual when you inherit from a class which has a
virtual dtor, even if you don't add virtual yourself. This is transitive;
if your grandparent has a virtual dtor, your parent will have a virtual
dtor even if it doesn't use virtual, and you will too.

Quote:
Then I started thinking about when you would get caught out in other cases -
would it only be when you have explicitly used new & delete within your
class hierarchy somewhere? I am saying this because I assume that non-heap
variables manage their own destruction. How about when your hierarchy uses
containers from the standard library? I expect them to manage their own
destruction like built-in types.

The problem solved by virtual destructors is deletion of a derived object
through a base pointer. The standard library containers make copies of
their contents, so these will slice the derived part before insertion.
Therefore a list<Base> never needs to delete a Derived object. The
same applies to global and local variables; the compiler knows their
exact type.
Containers when used as members are no problem; they have normal
semantics. ( "Value Type", see below )

Quote:
If virtual destructors are only required when the hierarchy contains
explicit new/delete usage, then do smart pointers remove the need for
virtual destructors? If so, are there any reliability/speed recommendations
for the implementation of those smart pointers (I'm mainly aware of Boost &
Loki).

The assumption is wrong, though. These smart pointers usually call delete
for you. When you pass a Derived* to a smart_ptr<Base>, it will call
'delete base_pointer;' for you. This means deletion of a Derived object
through a base pointer, so you must again provide a virtual dtor.

The rule is somewhat simpler if you make a distinction between two
comon kinds of types. The first kind is the Value Type. Examples
are int, std::string or std::map<std::string, float>. These types
don't have virtual functions and can be copied and assigned without
loss of information ( although this may be inefficient for large
objects). These can directly be used as members of other types.

The second kind is the OO Type. These types do have virtual destructors,
base classes (often abstract) and usually more complex behavior. They
cannot be copied easily, and therefore are passed around by reference
or (smart) pointer. When these objects must be copied, a virtual clone()
method must be provided: Even if your function has a Derived& argument,
someone may pass in a EvenMoreDerived object. An example is
std::ofstream. If you want to use these types as members, you will need
to add a (smart) pointer to your class. The copy ctor that would be
generated would copy only this pointer, so you often need to
suppress it - either provide your own, which calls clone() or make
it private unimplemented. You can't use these pointers directly
in a std::container, but a std::container<smart_ptr does
work.

This distinction isn't 100%; e.g. exception objects are neither. However,
the types most used in your programs will be one of these two kinds.

Regards,
Michiel Salters

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Rob
Guest





PostPosted: Fri Apr 16, 2004 6:26 am    Post subject: Re: Requirements for virtual destructors Reply with quote

"Michael" <mwh_acs (AT) hotmail (DOT) com> wrote

Quote:


Hi all

After having initially put virtual destructors in _all_ classes that get
derived from, due to the dire warnings from the respected references about
the consequences of not doing so, I am now trying to get a bit more
sophisticated about it.

First rule I read along these lines was that a class only needs a virtual
destructor if it has at least one virtual function - is that agreed here?

I won't claim to speak for the "here", but I don't agree with this. If a
class has at least one virtual function, that is often a hint that other
classes can/should be derived from it.

The only time a virtual destructor is needed is if a pointer to a Base
class can point at an instance of a derived class, and an attempt can
be made to delete that pointer. It is possible to meet that condition
without the Base having any virtual functions (other than the destructor).

Consider this example (contrived to illustrate the point, not to advocate
any particular practice)

class Base
{
int x;
public:
Base(int i) : x(i) {};
~Base();
void Print() {std::cout << x << 'n';};
};

class Derived
{
public:

Derived() : Base(42) {};
};

main()
{
Base *b = new Derived;
b->Print();
delete b;
}

This example will yield undefined behaviour when deleting b,
unless Base has a virtual destructor. No other virtual function
in sight.

Quote:
How about if it doesn't have any virtual functions but is itself derived
from? More generally, how about if it's in the middle of a hierarchy with
all sorts of concrete and abstract classes above and below it, some of
which
have their own virtual destructors?

I'll avoid debates on whether a class should or shouldn't be derived from
concrete classes. There are some learned people (eg Scott Meyers)
who say that's a bad thing.

That aside .....

The question of a virtual destructor comes down to whether an object can
be deleted through a pointer to a base. Being in the middle of a hierarchy
doesn't change that. If a base class can be handled in this way, the base
class
requires a virtual destructor. All derived classes will therefore have a
virtual
destructor, whether explicitly declared or not.

If you have a situation of C derived from B derived from A, and it is ever
possible
to delete a C through a pointer to B, then B requires a virtual destructor.
If A does not have a virtual destructor, this means that B must declare its
destructor
virtual. If A has a virtual destructor, B will already have a virtual
destructor and
declaring it again won't hurt.

For example

main()
{
B *b = new C;
delete b; // requires B's destructor to be virtual
A *a = new C;
delete a; // requires A's destructor to be virtual
// (which implies B's will be do).
}


Quote:

Then I started thinking about when you would get caught out in other
cases -
would it only be when you have explicitly used new & delete within your
class hierarchy somewhere? I am saying this because I assume that
non-heap
variables manage their own destruction. How about when your hierarchy
uses
containers from the standard library? I expect them to manage their own
destruction like built-in types.

"non-heap variables" presumably means "not allocated with operator new" i.e.
not dynamically allocated.

If an object is not dynamically allocated, it shouldn't be deleted under any
circumstance. So having it's destructor virtual makes no difference.

In general, it is difficult to prevent deleting an instance of a derived
class
through a pointer to base .... those users of your code are hard to predict.
There are some techniques (eg private constructors, supplying an operator
new()) that, used in combination could prevent dynamic creation of objects.
In general, unless you can prevent dynamic creation of objects, you need to
assume they can be deleted. Which means you need to consider whether
an object can be deleted through a pointer to it's Base.......

If a class is derived from standard containers, then you can not use a
pointer
to those containers to delete the object (standard containers don't have
virtual destructors). So

class X : public std::vector<float>
{
// whatever
}

main()
{
std::vector<float> x = new X;
delete x;
}

will always yield undefined behaviour.

If standard containers are *members* of your classes, then those data
members will clean themselves up as usual.

Quote:

If virtual destructors are only required when the hierarchy contains
explicit new/delete usage, then do smart pointers remove the need for
virtual destructors? If so, are there any reliability/speed
recommendations
for the implementation of those smart pointers (I'm mainly aware of Boost
&
Loki).

Depends on the smart pointer and how it's used.

If the raw pointer managed by a smart pointer can point at a derived class
instance through a base class pointer, all of the preceding arguments come
back. If not, then they don't.

Reliability and speed implementations for smart pointers tends to depend
more
on the way the smart pointer decides to clean up the object it manages.





[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Thomas Richter
Guest





PostPosted: Fri Apr 16, 2004 10:06 am    Post subject: Re: Requirements for virtual destructors Reply with quote


Hi,
Quote:

First rule I read along these lines was that a class only needs a virtual
destructor if it has at least one virtual function - is that agreed here?

A class needs a virtual destructor in case you want to destruct it thru one
of its base classes/chances are that you destruct it thru one of its base
classes.

This happens typically for polymorphic classes, thus for classes with
other virtual functions. Thus,

a) if your class is never used polymorphically, chances are that on destruction
static and runtime type are identically. A nonvirtual destructor would do.

b) if your class is used polymorphically, chances are that your code uses
a pointer to the base class for destroying it. Then the destructor must be
virtual.

There's no one-to-one rule. It depends on what you're doing. a) and b) are
rules of thumb. (I can think of constructed cases where a) is wrong, and
also some cases where b) is wrong that are a bit less constructed).

Quote:
How about if it doesn't have any virtual functions but is itself derived
from? More generally, how about if it's in the middle of a hierarchy with
all sorts of concrete and abstract classes above and below it, some of which
have their own virtual destructors?

First of all, if the base class has a virtual destructor, every derived class
will have, no matter whether you put "virtual" in front of it or not.

Second, there's no requirement that a base class of a polymorphical class
is polymorphic itself, or a base class requiring a virtual destructor must
be virtual.

Think of the following: In places where to have "class B *b" and you write
a "delete b", can you guarantee that the runtime type of "*b" is "B"
and not that of a derived class? In the second case, B's destructor must
be virtual. If not, there's no need to.

Quote:
Then I started thinking about when you would get caught out in other cases -
would it only be when you have explicitly used new & delete within your
class hierarchy somewhere?

Except for some pretty special cases (calling destructors explicitly),
I'd say so. The reason is that for automatic variables, construction happens
in the same block as destruction, and construction requires the static type
which will then be the runtime type of the object constructed.

Quote:
I am saying this because I assume that non-heap
variables manage their own destruction. How about when your hierarchy uses
containers from the standard library? I expect them to manage their own
destruction like built-in types.

Every type manages its own destruction, so to say. That's why we need to
write destructors. The question rather is whether you can proof that the
static type at the time of destruction equals the dynamic type.

Quote:
If virtual destructors are only required when the hierarchy contains
explicit new/delete usage, then do smart pointers remove the need for
virtual destructors?

No, because you can assign a smart-pointer to a base class to a pointer
to a derived class object. auto_ptrs are no different in this case to
C-style pointers.

So long,
Thomas


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Ben Hutchings
Guest





PostPosted: Fri Apr 16, 2004 2:49 pm    Post subject: Re: Requirements for virtual destructors Reply with quote

Michael wrote:
Quote:
After having initially put virtual destructors in _all_ classes that get
derived from, due to the dire warnings from the respected references about
the consequences of not doing so, I am now trying to get a bit more
sophisticated about it.

First rule I read along these lines was that a class only needs a virtual
destructor if it has at least one virtual function - is that agreed here?
How about if it doesn't have any virtual functions but is itself derived
from?

That's a fairly good rule of thumb. A virtual destructor is required
where the dynamic type (actual type) of an object being destroyed/
deleted is different from its static type (the type it is seen as
having at compile time). So a class only needs a virtual destructor
if instances of a derived class may be deleted through a pointer to
the base class type or, unusually, explicitly destroyed through a
pointer or reference to the base class type.

Deletion through a pointer-to-base is only likely to be done if that
base class is designed for polymorphism, in which case it will have
virtual functions besides the destructor. If the base class is
designed for use in some other way (e.g. std::iterator
specialisations) then it won't need any virtual functions, even a
virtual destructor.

Quote:
More generally, how about if it's in the middle of a hierarchy with
all sorts of concrete and abstract classes above and below it, some of which
have their own virtual destructors?

If a class has a virtual destructor, the destructor of any class
derived from it is virtual even if this isn't explicit in its
declaration or if the declaration itself is not explicit.

Quote:
Then I started thinking about when you would get caught out in other cases -
would it only be when you have explicitly used new & delete within your
class hierarchy somewhere? I am saying this because I assume that non-heap
variables manage their own destruction. How about when your hierarchy uses
containers from the standard library? I expect them to manage their own
destruction like built-in types.

The type difference does not occur for objects in automatic or static
storage, member objects, or elements of containers.

Quote:
If virtual destructors are only required when the hierarchy contains
explicit new/delete usage, then do smart pointers remove the need for
virtual destructors? If so, are there any reliability/speed recommendations
for the implementation of those smart pointers (I'm mainly aware of Boost &
Loki).

This is possible, depending on how the smart pointers are designed.
Since they use new and delete internally, they will generally require
virtual destructors in the same cases. However I know that Boost's
shared_ptr<T> will call the proper destructor for an object of a
derived class even if it isn't virtual in T, or even if T is void.

Quote:
Apologies for the lack of clarity here - still climbing that famously steep
C++ learning curve! ;o)

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Harald Nowak
Guest





PostPosted: Fri Apr 16, 2004 2:51 pm    Post subject: Re: Requirements for virtual destructors Reply with quote

Hi there!

Quote:
First rule I read along these lines was that a class only needs a virtual
destructor if it has at least one virtual function - is that agreed here?

No. It should have a virtual destructor if you're planning to delete the
class through a pointer of base type. e.g.:

Base *p = new Derived() ;
delete p ; // if dtor not virtual, Base's dtor will be called here

Quote:
Then I started thinking about when you would get caught out in other cases -
would it only be when you have explicitly used new & delete within your
class hierarchy somewhere?

In some sense, yes: if you mean by your statement, ONLY if ever anybody
calls
new/delete on your class you are right. Auto objects don't need that,
because
their type is exactly known at destruction time by the compiler.

Quote:
If virtual destructors are only required when the hierarchy contains
explicit new/delete usage, then do smart pointers remove the need for
virtual destructors?

Interesting question - I would say it depends upon the smart pointer.
If the smart pointer would itself delete through a pointer of base type,
then no - virtual dtors would be needed. If the smart pointer is
strongly
typed and never has the type Base when it actually points to a Derived
then
maybe yes - but you will generally not want to prevent the possibility
of an assignment of a Derived object to a smart pointer of type "<Base
*>".
Only if you allow this, your smart pointer will behave similar to
builtin types.

Anybody correct me, if I'm wrong here.

regards,
Harald Nowak

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Frédéric Lachasse
Guest





PostPosted: Fri Apr 16, 2004 4:07 pm    Post subject: Re: Requirements for virtual destructors Reply with quote

"Michael" <mwh_acs (AT) hotmail (DOT) com> wrote

Quote:


Hi all

After having initially put virtual destructors in _all_ classes that get
derived from, due to the dire warnings from the respected references about
the consequences of not doing so, I am now trying to get a bit more
sophisticated about it.

The only rule is: you need (and have to) have a virtual destrutor in a base
class if you need to call the destructor through a pointer to this base
class.

Quote:
First rule I read along these lines was that a class only needs a virtual
destructor if it has at least one virtual function - is that agreed here?

The presence of a virtual function in a base class is a sign that this class
will be a base class for polymorphic objects, and that means using derived
object through a pointer to the base class, and very often, destruction of
objects through pointers to the base class. That "very often" is not
"always", so that is not an absolute rule.

Quote:
How about if it doesn't have any virtual functions but is itself derived
from? More generally, how about if it's in the middle of a hierarchy with
all sorts of concrete and abstract classes above and below it, some of
which
have their own virtual destructors?

There is a special rule with virtual destructor: if a parent class has a
virtual destructor, the destructor of all its children and derived classes
will have their destructor virtual, even if you define it without the
virtual keyword.

And to know if you need the virtual destructor, see rule #1 above.

Quote:
Then I started thinking about when you would get caught out in other
cases -
would it only be when you have explicitly used new & delete within your
class hierarchy somewhere? I am saying this because I assume that
non-heap
variables manage their own destruction. How about when your hierarchy
uses
containers from the standard library? I expect them to manage their own
destruction like built-in types.

Standard library containers store objects by values, so no polymorphic
objects. So you never need virtual destructors for object stored in such
containers.

(For those who think: but you can put pointers or smart pointers of
polymorphic objects, that is true. But the pointers or smart pointers
actually stored in the containers are not polymorphic objects. The
responsability of destroying the pointed object is then the responsability
of the pointer, not the container.)

Quote:
If virtual destructors are only required when the hierarchy contains
explicit new/delete usage, then do smart pointers remove the need for
virtual destructors?

If the smart pointers use pointers to the base class and use "delete" to
free the object (which is the common case), then you need the virtual
destructor in the base class:

// Undefined behavior if Base destructor not virtual
auto_ptr<Base> ap = new Derived;

// But here, it is not necessary
auto_ptr<Derived> ap = new Derived;

Quote:
If so, are there any reliability/speed recommendations
for the implementation of those smart pointers (I'm mainly aware of Boost
&
Loki).

The only important thing is how you destroy the pointed object. The very
common case for polymorphic objects is using "delete" on a pointer to base,
either directly on a dumb pointer or indirectly with a smart pointer object.
That is the basis for this rule: polymorphic object --> virtual destructor.

But this is not absolute. A classic (but rather uncommon) case is reference
counted objects using the addRef/release scheme:

class Base {
protected:
~Base() {}
public:
virtual void addRef() = 0;
virtual void release() = 0;
};

In this case, deletion is done by calling the (necessarilly) virtual
release() method instead of delete (and note that the destructor is
protected to avoid a direct usage of delete on a pointer to Base).

Quote:
Apologies for the lack of clarity here - still climbing that famously
steep
C++ learning curve! ;o)

I hope that I was clear enough.

--
Frédéric Lachasse - ECP86


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Michael
Guest





PostPosted: Fri Apr 16, 2004 5:06 pm    Post subject: Re: Requirements for virtual destructors Reply with quote


Thanks to all for interesting discussion.

It looks like the pragmatic approach of always adding a virtual dtor in the
base class is good as a default.

M

_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

_/ _/ _/_/_/ Hopkins Research Limited
_/ _/ _/ _/
_/_/_/_/ _/_/_/ Optimal Solutions via Virtual Systems
_/ _/ _/ _/
_/ _/ _/ _/ Tel: +44(0) 781 3467 381

_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

`All models are wrong, but some are useful' - George Box




-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
-----== Over 100,000 Newsgroups - 19 Different Servers! =-----

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
James Dennett
Guest





PostPosted: Sun Apr 25, 2004 11:26 pm    Post subject: Re: Requirements for virtual destructors Reply with quote

Harald Nowak wrote:
Quote:
Hi there!


First rule I read along these lines was that a class only needs a virtual
destructor if it has at least one virtual function - is that agreed here?


No. It should have a virtual destructor if you're planning to delete the
class through a pointer of base type. e.g.:

Base *p = new Derived() ;
delete p ; // if dtor not virtual, Base's dtor will be called here

We should be clear and say that this gives undefined behavior
if Base::~Base is non-virtual. Calling the base destructor but
not the derived destructor is just one possible thing that could
happen. It's not guaranteed. Nothing is guaranteed if the
static type doesn't match the dynamic type and the base dtor
is non-virtual.

-- James.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Jerald Fijerald
Guest





PostPosted: Mon Apr 26, 2004 10:07 pm    Post subject: Re: Requirements for virtual destructors Reply with quote

Michael <mwh_acs (AT) hotmail (DOT) com> wrote

Quote:
Thanks to all for interesting discussion.

It looks like the pragmatic approach of always adding a virtual dtor in the
base class is good as a default.


I didn't see anyone mention this. So, there are two cases you
will need a virtual destructor.

1) As pointed out, when deleting derrived objects with pointers
to base and "you want to invoke a destructor to take some
actions". If, for example, classes have no destructors (because
there's nothing to destruct), no need to add empty dtors just
for doing so. In this case, virtual dtor is the only way to
invoke the correct dtor.

2) I don't know how the standard describes this, but in multiple
inheritance, like:

class C : A, B { ... };

if you delete the object from a pointer to 'B' and there are no
virtual dtors, you have a crash!!

It seems that the rule "always put virtual dtor in base classes"
exists only because it's too furstrating to explain when a virtual
dtor is really needed by the language. For the second case, I'd
say:

- always put virtual dtors in multuple inheritance if deleting
with pointer to 'B'.

- always put virtual dtor in "virtual inheritance".

Gerald

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.