Questions of C++ FAQ

C

ctick

In C++ FAQ 20.5, "...here are the mechanical details of why you need a
virtual destructor when someone says delete using a Base pointer that's
pointing at a Derived object. When you say delete p, and the class of p has
a virtual destructor, the destructor that gets invoked is the one associated
with the type of the object *p, not necessarily the one associated with the
type of the pointer. This is A Good Thing. In fact, violating that rule
makes your program undefined."

What's "the class of p", Base class?

What's "the type of the object *p", Base or Derived?

"the destructor that gets invoked is..."
Both destructors in Base AND Derived are invoked. Why only one is mentioned
here?

Thanks in advance!
 
A

Alf P. Steinbach

* ctick:
In C++ FAQ 20.5, "...here are the mechanical details of why you need a
virtual destructor when someone says delete using a Base pointer that's
pointing at a Derived object. When you say delete p, and the class of p has
a virtual destructor, the destructor that gets invoked is the one associated
with the type of the object *p, not necessarily the one associated with the
type of the pointer. This is A Good Thing. In fact, violating that rule
makes your program undefined."

What's "the class of p", Base class?
Yes.


What's "the type of the object *p", Base or Derived?

The same as above, Base.

The FAQ could need a little rewording here, yes.


"the destructor that gets invoked is..."
Both destructors in Base AND Derived are invoked. Why only one is mentioned
here?

Both are invoked if the one in Base is virtual.

Otherwise only the one in Base is invoked.

The reason only one is mentioned is because only the one that is
directly invoked by the delete expression is relevant. When the one in
Derived is directly invoked (as can happen when you have a Derived*
pointer) it doesn't matter whether the Base destructor is virtual or
not, because the Derived destructor knows that Derived is derived from
Base, and invokes the Base destructor automagically. When the one in
Base is the one directly invoked, as happens when the pointer is a Base*
and the destructor in Base is non-virtual, it doesn't know anything
about any Derived object needing destruction. So nothing more happens.
 
A

Alf P. Steinbach

* Alf P. Steinbach:
* ctick:

The same as above, Base.

Oops, I meant of course Derived. *p is the object that p points to.
Which in this case is a Derived object.

The FAQ could need a little rewording here, yes.

Absolutely! ;-)
 
E

E. Robert Tisdale

ctick said:
In C++ FAQ 20.5, "...here are the mechanical details
of why you need a virtual destructor when someone says delete
using a Base pointer that's pointing at a Derived object.
When you say delete p, and the class of p has a virtual destructor,
the destructor that gets invoked
is the one associated with the type of the object *p,
not necessarily the one associated with the type of the pointer.
This is A Good Thing.
In fact, violating that rule makes your program undefined."

This is bad advice and typical of the muddled thinking
that passes for "object oriented programming" these days.
What's "the class of p", Base class?

Pointer p is a pointer to an object of the Base type.
What's "the type of the object *p", Base or Derived?

Reference *p is a reference to an object of the Base type.
What the author means is that
p was converted from a pointer to an object of the Derived type
to a pointer to an object of the Base type.
Invocation of a virtual function for the Base type
will actually invoke the corresponding function
defined for the Derived type.
"the destructor that gets invoked is..."
Both destructors in Base AND Derived are invoked.
Why only one is mentioned here?

The author was simply careless.
Evidently, the author believes that,
when programmers write

delete p;

they mean to delete an object of the Derived type
if p was actually converted from a pointer
to an object of a Derived type.

This is a *very* weak argument for a *virtual* destructor.
The Base class could have defined a virtual member function:

void Base::free(void) const {
delete this;
}

to accompany a "virtual constructor" member function:

Base* Base::allocate(void) {
return new Base;
}

The problem here is that so-called "object oriented programmers"
are attempting to mimic Java programmers. But C++ is *not* Java.
Java has a built-in garbage collector to clean up dangling references
so that Java programmers needn't worry about memory leaks.
 
J

JKop

ctick posted:
In C++ FAQ 20.5, "...here are the mechanical details of why you need a
virtual destructor when someone says delete using a Base pointer that's
pointing at a Derived object. When you say delete p, and the class of p
has a virtual destructor, the destructor that gets invoked is the one
associated with the type of the object *p, not necessarily the one
associated with the type of the pointer. This is A Good Thing. In fact,
violating that rule makes your program undefined."

What's "the class of p", Base class?

What's "the type of the object *p", Base or Derived?

"the destructor that gets invoked is..."
Both destructors in Base AND Derived are invoked. Why only one is
mentioned here?

Thanks in advance!

Imagine the following:

When a mammal, dies it exhales.

A dog is a mammal. Therefore when it dies it exhales. But my dog also barks
too when it dies.

Here we go:

class Mammal
{
public:

~Mammal(void)
{
Exhale();
}
};

class Dog : public Mammal
{
public:

~Dog(void)
{
Bark();
}
};


int main(void)
{
Dog* Sparky = new Dog;

delete Sparky; //Here, it barks, then it dies

//Now imagine that this is a wildlife centre for mammals. They'd don't
//care whether it's a dog or cat or monkey or rhino... they just care
//that it's a mammal. Take the following:

Mammal* Sparky2 = new Dog;

delete Sparky2; //Here, it DOESN'T bark before it dies.

//If Mammal had had a virtual destructor, then Yes, it would have
//barked before it died!
}
 
J

John Carson

E. Robert Tisdale said:
This is bad advice and typical of the muddled thinking
that passes for "object oriented programming" these days.

Pointer p is a pointer to an object of the Base type.


Reference *p is a reference to an object of the Base type.
What the author means is that
p was converted from a pointer to an object of the Derived type
to a pointer to an object of the Base type.
Invocation of a virtual function for the Base type
will actually invoke the corresponding function
defined for the Derived type.

The author was simply careless.
Evidently, the author believes that,
when programmers write

delete p;

they mean to delete an object of the Derived type
if p was actually converted from a pointer
to an object of a Derived type.

This is a *very* weak argument for a *virtual* destructor.
The Base class could have defined a virtual member function:

void Base::free(void) const {
delete this;
}

to accompany a "virtual constructor" member function:

Base* Base::allocate(void) {
return new Base;
}

The problem here is that so-called "object oriented programmers"
are attempting to mimic Java programmers. But C++ is *not* Java.
Java has a built-in garbage collector to clean up dangling references
so that Java programmers needn't worry about memory leaks.


I wonder what language you are trying to program in or whether you read the
full text of this particular FAQ. The FAQ refers to a situation in which
Base pointers may point to Derived objects, presumably in order to achieve
polymorphic behaviour. The programmer calls delete on these Base pointers
without knowing --- and without wanting to know --- the kind of object that
is pointed to. Making the destructors virtual ensures that the correct
destructor(s) will be called. This is a simple and elegant procedure.
 
E

E. Robert Tisdale

John said:
I wonder what language you are trying to program in
or whether you read the full text of this particular FAQ.
The FAQ refers to a situation
in which Base pointers may point to Derived objects,
presumably in order to achieve polymorphic behaviour.
The programmer calls delete on these Base pointers
without knowing --- and without wanting to know ---
the kind of object that is pointed to.
Making the destructors virtual ensures that
the correct destructor(s) will be called.
This is a simple and elegant procedure.

It is an elegant procedure in *Java*.
In C++, it is a souce of memory leaks.
 
J

John Carson

E. Robert Tisdale said:
It is an elegant procedure in *Java*.
In C++, it is a souce of memory leaks.


If you are referring to the manual calling of delete and hence the
possibility that the programmer may forget to call it, then this can be
handled by the use of smart pointers. The destructor must still be virtual.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,008
Latest member
Rahul737

Latest Threads

Top