Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

virtual destructor

89 views
Skip to first unread message

Saurabh

unread,
Jun 12, 2002, 3:25:05 AM6/12/02
to
hi

we cannot have virtual constructor, but we cam have virtual destructor.
pls anybody tell me what is the logic behind this virtual destructor.
if someone could send me some sample code for it.

bye
saurabh.

Dimitris Kamenopoulos

unread,
Jun 12, 2002, 4:04:51 AM6/12/02
to
Saurabh wrote:

Hi,

Your can find (very good) answers in the FAQ:
http://www.parashift.com/c++-faq-lite/

--
People in cars cause accidents. Accidents in cars cause people.

josh

unread,
Jun 11, 2002, 11:43:47 PM6/11/02
to
On 12 Jun 2002 00:25:05 -0700, scorp...@rediffmail.com
(Saurabh) wrote:
> we cannot have virtual constructor, but we cam have virtual
> destructor. pls anybody tell me what is the logic behind this
> virtual destructor.
Exactly the same as behind *any* virtual function. Nothing
special about destructors as far as virtualness. The FAQ has
more detail, but that's the gist of it.

Ron Natalie

unread,
Jun 12, 2002, 10:19:15 AM6/12/02
to

Actually there are two major points about virtual destructors:

A virtual destructor in a class will make destructors in
classes derived from that class virtual. Destructors aren't
inerhitted/overriden in the sense of normal member functions
but the virtual propagates to the derived destructors.

If you delete an object via a pointer to a base class, the behavior
is not defined unless the base class destructor is virtual.

Marco Trincardi

unread,
Jun 12, 2002, 10:39:17 AM6/12/02
to

Hi saurabh,
you can find a good motivation for using a virtual destructor in the
definition of an Abstract Class.
Take a look at Stroutstrup C++ Programming Language (3d edition) section
12.4.2

> bye
> saurabh.

bye

Marco

josh

unread,
Jun 12, 2002, 11:46:31 AM6/12/02
to
On Wed, 12 Jun 2002 10:19:15 -0400, Ron Natalie
<r...@sensor.com> wrote:
> josh wrote:
> >
> > On 12 Jun 2002 00:25:05 -0700, scorp...@rediffmail.com
> > (Saurabh) wrote:
> > > we cannot have virtual constructor, but we cam have
virtual
> > > destructor. pls anybody tell me what is the logic behind
this
> > > virtual destructor.
> > Exactly the same as behind *any* virtual function. Nothing
> > special about destructors as far as virtualness. The FAQ
has
> > more detail, but that's the gist of it.
>
> Actually there are two major points about virtual
> destructors:
>
> A virtual destructor in a class will make destructors in
> classes derived from that class virtual.
Right.

> Destructors aren't inerhitted/overriden in the sense of
> normal member functions but the virtual propagates to the
> derived destructors.

Right, but any destructors do that, not only virtual. So, the
point of using virtual ones is to achieve the first major point
you've mentioned -- the get the *right* destructor called
first, even if invoked via a base pointer. Which is the same as
with any virtual function.



> If you delete an object via a pointer to a base class, the
> behavior is not defined unless the base class destructor is
> virtual.

Why is that? I thought the destructor of the type that the
pointer is declared to point to will be invoked.

Ron Natalie

unread,
Jun 12, 2002, 5:23:19 PM6/12/02
to

josh wrote:
>
> Right, but any destructors do that, not only virtual. So, the
> point of using virtual ones is to achieve the first major point
> you've mentioned -- the get the *right* destructor called
> first, even if invoked via a base pointer. Which is the same as
> with any virtual function.

No, it's got nothing to do with the "right" destructor.
When an object is properly destroyed, all the destructors
are called in the proper order.

The point I was making is that destructors don't behave like
normal functions when it comes to inheritance overriding. If
it was, you'd need to declare a Derved::~Base() to get it to
work.

> > If you delete an object via a pointer to a base class, the
> > behavior is not defined unless the base class destructor is
> > virtual.
> Why is that? I thought the destructor of the type that the
> pointer is declared to point to will be invoked.

I can't even parse the last statement. The rule is exactly
as I stated it. The destructor of the static type of the pointer
must be virtual:

class Base {
public:
~Base() { }
};

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

Base* bp = new Derived;
delete bp;

The delete is undefined behavior. Essentially the presence of
a virtual destructor on Base signifies that there MIGHT be a
derived object there. There is MORE to the destruction of an
object than just calling the destructor (hint: you also have
to get rid of the memory).

David White

unread,
Jun 12, 2002, 7:31:36 PM6/12/02
to
Ron Natalie <r...@sensor.com> wrote in message
news:3D07BBC7...@sensor.com...
> class Derived {

I assume this was meant to be: class Derived : public Base {

> public:
> virtual ~Derived() { }
> };
>
> Base* bp = new Derived;
> delete bp;
>
> The delete is undefined behavior. Essentially the presence of
> a virtual destructor on Base signifies that there MIGHT be a
> derived object there. There is MORE to the destruction of an
> object than just calling the destructor (hint: you also have
> to get rid of the memory).

I don't see how it can be undefined.

class Base {
char *baseBuf;
public:
~Base() { delete baseBuf; }
};

class Derived : public Base {
char *derivedBuf;
public:
virtual ~Derived() { delete derivedBuf; }
};

Base* bp = new Derived;
delete bp;

Are you saying that the delete above might not result in the deletion of
baseBuf? How is the behaviour undefined?

David

David White

unread,
Jun 12, 2002, 7:46:05 PM6/12/02
to

David White <wi...@not.give.email> wrote in message
news:MPQN8.3574$06.4...@nasal.pacific.net.au...

> Are you saying that the delete above might not result in the deletion of
> baseBuf? How is the behaviour undefined?
>

Sorry. I completely ignored your hint and concentrated on the destructors
problem.

David

josh

unread,
Jun 12, 2002, 2:49:32 PM6/12/02
to
On Wed, 12 Jun 2002 17:23:19 -0400, Ron Natalie
<r...@sensor.com> wrote:
> josh wrote:
> >
> > Right, but any destructors do that, not only virtual. So,
> > the point of using virtual ones is to achieve the first
> > major point you've mentioned -- the get the *right*
> > destructor called first, even if invoked via a base
> > pointer. Which is the same as with any virtual function.
>
> No, it's got nothing to do with the "right" destructor.

Yes, it's got everything to do with calling the right
destructor -- the destructor of the class the actual object is
an instance of, rather than of the class that the pointer is
declared to point to. Which is the same idea as with any
virtual function.


> When an object is properly destroyed, all the destructors
> are called in the proper order.

That is *always* the case, whether the destructor is virtual or
not, the problem is to start with the destructor of the actual
class of the physical object rather than with the class that
the pointer happens to be declared to point to. If the pointer
is declared to point to a base class, in the case of a non-
virtual destructor, this base class's destructor will be called
(I'm not sure about undefined behaviour here), not the
destructor of the derived class that the pointer in question
actually points to.


> The point I was making is that destructors don't behave like
> normal functions when it comes to inheritance overriding.

Partially correct, but that wasn't the question. The
question is how the call is dispatched, not what happens after
the dispatched-to function/destructor is entered (which doesn't
have anything to do with how the function was reached -- via a
pointer or whatever; once you've entered the function the
question of virtualness is out of the picture.)

ALL destructors, virtual or not, are always called along the
inheritance tree from the apparent type down to the very base
class. What was at issue here was what does having a *virtual*
destructor buy you. It is totally unrelated to how destructor
chain is "unwound" in general. You need a *virtual* destructor
so that even if an entity is pointed to via a *base-class*
pointer, the destructor of *this entity's ACTUAL class* will be
called nevertheless. Which is how all virtual functions
operate. That virtual (and any other) functions don't channel
the call to the base classes is correct of course, but
irrelevant in the context of the discussion. We're discussing
*virtual* destructors vs *non-virtual* destructors, not
destructors vs member functions.


> > > If you delete an object via a pointer to a base class,
> > > the behavior is not defined unless the base class
> > > destructor is virtual.

I didn't know that. I thought the destructor of the class that
the pointer is declared to point to will be called. Are you
sure it's undefined? Pointing to an object of a class with a
non-virtual destructor is a legal situation, why would the
behaviour in that case be undefined? I mean, how is the
compiler gonna distiguish between a badly-designed polymorphic
class and a plain, non-polymorphic class? This is not a
rhetorical question, I actually don't know for sure, but
undefined behavour here doesn't sound right.


> > Why is that? I thought the destructor of the type that the
> > pointer is declared to point to will be invoked.
>
> I can't even parse the last statement.

<g>. Yeah, it's clumsy. OK, here goes:
(I thought) the destructor ( of the type [that the pointer is
declared to point to] ) will be invoked.

MyBaseClass* ptr; the "ptr" is declared to point to objects of
MyBaseClass type.

MyNewClass: pub MyBaseClass ...

MyBaseClass* ptr = new MyNewClass;
..
delete ptr;

Here, if MyBaseClass's destructor (and thus all derived
classes' destructors) is virtual, _MyNewClass's_ destructor
will be called even though it's not the ptr's type. Same as
with any virtual function in that hierarchy. If not, then (I
think) MyBaseClass's destructor will be called even though ptr
actually points to an instance of MyNewClass not MyBaseClass.

You say it'll be undefined, I didn't know that, and it doesn't
seem right, coz in general it's not an illegal context. The
compiler doesn't "know" that MyBaseClass _should have_ had a
virtual destructor, for the compiler MyBaseClass is simply a
non-polymorphic class with a non-virtual destructor (which is
not illegal or meaningless per se), so that's what it will
directly (not via vtable) dispatch the call to, I would think.

Adam H. Peterson

unread,
Jun 12, 2002, 7:58:23 PM6/12/02
to
<snip>

> I didn't know that. I thought the destructor of the class that
> the pointer is declared to point to will be called. Are you
> sure it's undefined?

It's undefined because the standard says it's undefined. This leaves
compiler vendors free to put whatever magic they want into the compiler
generated portion of the con-/de-structor without having to worry about
mismatched con-/de-structor calls.

> Pointing to an object of a class with a
> non-virtual destructor is a legal situation, why would the
> behaviour in that case be undefined?

I believe they chose to make it undefined to allow more flexibility in QofI
for the compiler makers.

> I mean, how is the
> compiler gonna distiguish between a badly-designed polymorphic
> class and a plain, non-polymorphic class? This is not a
> rhetorical question, I actually don't know for sure, but
> undefined behavour here doesn't sound right.

Probably what happens is that the base destructor _is_ invoked instead of
the derived destructor. But the standard doesn't specify exactly what
implementation details are involved in the execution of a destructor, so it
places no constraints upon the results of a program that doesn't call the
right destructor for the right class.

For instance, the most derived destructor is responsible for destroying
shared bases. A compiler might hard code the offsets of the virtual bases
into the destructor for the most derived type, knowing that it will only be
called on the most derived type. But if you call the wrong most-derived
destructor, those offsets are likely to be wrong. It could blow up in your
face, cause a heap corruption, or do just about anything else.

<snip>

Adam Peterson


josh

unread,
Jun 12, 2002, 3:44:46 PM6/12/02
to
On Wed, 12 Jun 2002 17:58:23 -0600, "Adam H. Peterson"
<ah...@email.byu.edu> wrote:
> <snip>
> > I didn't know that. I thought the destructor of the class
> > that the pointer is declared to point to will be called.
> > Are you sure it's undefined?
>
> It's undefined because the standard says it's undefined.
Oh, OK. That would do it <g>.

> Probably what happens is that the base destructor _is_
> invoked instead of the derived destructor.

That's what I've always observed in practice.

> But the standard doesn't specify exactly what
> implementation details are involved in the execution of a
> destructor, so it
> places no constraints upon the results of a program that
> doesn't call the right destructor for the right class.
>
> For instance, the most derived destructor is responsible for
> destroying shared bases. A compiler might hard code the

> offsets of the virtual basesinto the destructor for the most

> derived type, knowing that it will only be called on the most
> derived type. But if you call the wrong most-derived
> destructor, those offsets are likely to be wrong. It could
> blow up in your face, cause a heap corruption, or do just
> about anything else.

Very interesting, thanks. Off the top of your head, is this
discussed in the Stroustroup anywhere? I'd like to read that
in detail coz it still doesn't make a lot of sense to me. Of
course the *results* of having called a wrong destructor are
undefined, yeah, anything can happen, very likely something
bad, but is it undefined *which* destructor will be called
(regardless of the results of calling it, that is)?

I mean, offsets and stuff are hardcoded by the compiler
*inside* the generated function (destructor), and should have
nothing to do with the pointer this function is invoked through
or whether it's invoked via a pointer (???)

Just thinking aloud.

Adam H. Peterson

unread,
Jun 12, 2002, 9:01:14 PM6/12/02
to
<snip>

> Very interesting, thanks. Off the top of your head, is this
> discussed in the Stroustroup anywhere?

I don't know. <Confessions of a C++ programmer:> I've never read
Stroustrup. I've never even seen a copy.

> I'd like to read that
> in detail coz it still doesn't make a lot of sense to me. Of
> course the *results* of having called a wrong destructor are
> undefined, yeah, anything can happen, very likely something
> bad, but is it undefined *which* destructor will be called
> (regardless of the results of calling it, that is)?

The "as if" rule pretty much make the two equivalent. Heck, if a compiler
writer wanted to get crazy, he could make a program that didn't use function
calls at all. The compiler would be compliant, as long as the result is the
same _as_if_ it did.

<snip>

Adam Peterson


Pete Becker

unread,
Jun 12, 2002, 9:26:01 PM6/12/02
to
josh wrote:
>
> but is it undefined *which* destructor will be called
> (regardless of the results of calling it, that is)?
>

The behavior is undefined. End of sentence.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)

josh

unread,
Jun 12, 2002, 8:32:48 PM6/12/02
to
On Wed, 12 Jun 2002 21:26:01 -0400, Pete Becker
<peteb...@acm.org> wrote:
> josh wrote:
> >
> > but is it undefined *which* destructor will be called
> > (regardless of the results of calling it, that is)?
> >
>
> The behavior is undefined. End of sentence.
If that's all you can add to the topic, please kindly fuck off.
End of sentence.

josh

unread,
Jun 12, 2002, 8:36:50 PM6/12/02
to
On Wed, 12 Jun 2002 19:01:14 -0600, "Adam H. Peterson"
<ah...@email.byu.edu> wrote:
> <snip>
> > Very interesting, thanks. Off the top of your head, is this
> > discussed in the Stroustroup anywhere?
>
> I don't know. <Confessions of a C++ programmer:> I've never
> read Stroustrup. I've never even seen a copy.
<g> OK. I won't tell anyone.


> > I'd like to read that
> > in detail coz it still doesn't make a lot of sense to me.
> > Of course the *results* of having called a wrong destructor
> > are undefined, yeah, anything can happen, very likely
> > something bad, but is it undefined *which* destructor will
> > be called (regardless of the results of calling it, that
> > is)?
>
> The "as if" rule pretty much make the two equivalent. Heck,
> if a compiler writer wanted to get crazy, he could make a
> program that didn't use function calls at all. The compiler
> would be compliant, as long as the result is the
> same _as_if_ it did.

All right. I'm gonna investigate this, hopefully I can find
something.

David Schwartz

unread,
Jun 13, 2002, 5:57:31 AM6/13/02
to

He is right. If it's undefined, it's undefined. Anything can happen.
The obsenities don't help strengthen your position.

DS

Pete Becker

unread,
Jun 13, 2002, 8:53:14 AM6/13/02
to

PLONK.

Ruslan Abdikeev

unread,
Jun 13, 2002, 9:05:16 AM6/13/02
to
"josh" <jo...@xtreme.net> wrote in message news:1103_1023928368@l2092in-wllka-2...

Gosh!...

Ron Natalie

unread,
Jun 13, 2002, 9:38:18 AM6/13/02
to

josh wrote:
>
>
> That is *always* the case, whether the destructor is virtual or
> not, the problem is to start with the destructor of the actual
> class of the physical object rather than with the class that
> the pointer happens to be declared to point to.

You are assuming that all the destruction logic is implemented
in the destructor calling sequence. There is nothing in the C++
language that guarantees this.

> If the pointer
> is declared to point to a base class, in the case of a non-
> virtual destructor, this base class's destructor will be called
> (I'm not sure about undefined behaviour here), not the
> destructor of the derived class that the pointer in question
> actually points to.

Why don't you come back when you are sure. You are wrong.
It is outright undefined behavior. Perhaps in the tiny
examples you've tried all you get is the wrong destructor.
Try putting some allocation functions (operator new/delete)
in these classes. I guarantee you will see more untoward
behavior.

>
> Partially correct, but that wasn't the question. The
> question is how the call is dispatched, not what happens after
> the dispatched-to function/destructor is entered (which doesn't
> have anything to do with how the function was reached -- via a
> pointer or whatever; once you've entered the function the
> question of virtualness is out of the picture.)

None of which you claim as 'truth' is mandated by the C++
standard. You can not make these statements about the way
things are invoked.

> I didn't know that. I thought the destructor of the class that
> the pointer is declared to point to will be called. Are you
> sure it's undefined?

Yes, I'm sure. Even you should be able to see this in your
warped assumptions about how the destructors work. How is
the virtual call to the derived destructor going to work, if
the base class virtual funcction isn't virtual.

It's the same with any function:

struct Base {
void Function();
};
struct Derived : Base {
virtual void Function();
};

Base* bp = new Derived;

bp->Function(); // still calls Base::Function(), it's not virtual

Ron Natalie

unread,
Jun 13, 2002, 9:40:46 AM6/13/02
to

David White wrote:
>
>
>
> I don't see how it can be undefined.

Read the Standard. It's quite clear.

> class Base {
> char *baseBuf;
> public:
> ~Base() { delete baseBuf; }
> };
>
> class Derived : public Base {
> char *derivedBuf;
> public:
> virtual ~Derived() { delete derivedBuf; }
> };
>
> Base* bp = new Derived;
> delete bp;
>
> Are you saying that the delete above might not result in the deletion of
> baseBuf? How is the behaviour undefined?
>

Absolutely, actually, anything might result. You can't even be guaranteed
that the memory for the Derived object is freed properly. You *MIGHT* hose
whatever allocation scheme is present.

It's Base's destructor that needs to be virtual, the fact that Derived's
also becomes coincidentally virtual is not a factor.

Alexander Terekhov

unread,
Jun 13, 2002, 10:09:21 AM6/13/02
to

Pete Becker wrote:
>
> josh wrote:
> >
> > On Wed, 12 Jun 2002 21:26:01 -0400, Pete Becker
> > <peteb...@acm.org> wrote:
> > > josh wrote:
> > > >
> > > > but is it undefined *which* destructor will be called
> > > > (regardless of the results of calling it, that is)?
> > > >
> > >
> > > The behavior is undefined. End of sentence.
> > If that's all you can add to the topic, please kindly fuck off.
> > End of sentence.
>
> PLONK.

ROFLWTIME thanks.

regards,
alexander.

Alexander Terekhov

unread,
Jun 13, 2002, 11:04:12 AM6/13/02
to

Ron Natalie wrote:
[...]

> > Partially correct, but that wasn't the question. The
> > question is how the call is dispatched, not what happens after
> > the dispatched-to function/destructor is entered (which doesn't
> > have anything to do with how the function was reached -- via a
> > pointer or whatever; once you've entered the function the
> > question of virtualness is out of the picture.)
>
> None of which you claim as 'truth' is mandated by the C++
> standard. You can not make these statements about the way
> things are invoked.

Well, "undefined" stuff aside, how about *placement*-new
(std::nothrow_t versions and throws from c-tors aside)? To me,
the C++ standard pretty much >>MANDATES<< the 'manual' invocation
of the a proper [dynamic type] destructor:

p->~T(); // cleanup/destroy object
operator delete(p, /* something */); // reclaim storage

Frankly, I'd rather somehow try to 'delegate' it [i.e. proper
destructor(s) invocation, for all elements of dynamically
allocated arrays including] to the implementation too; just
like w.r.t. non-placement stuff [again, std::nothrow_t versions
and throws from c-tors aside]. Note that I'm NOT suggesting to
make objects keep track themselves the proper 'delete' (matching
the placement-new used to construct them) -- somehow make the
standard delete([])-expression somehow work even with non-
std::nothrow_t-placement-new(s) used to created objects and
arrays.

Or am I simply missing something?

regards,
alexander.

Ron Natalie

unread,
Jun 13, 2002, 12:07:22 PM6/13/02
to

Alexander Terekhov wrote:

> Well, "undefined" stuff aside, how about *placement*-new
> (std::nothrow_t versions and throws from c-tors aside)? To me,
> the C++ standard pretty much >>MANDATES<< the 'manual' invocation
> of the a proper [dynamic type] destructor:

It says the proper destructor(S) must be invoked for the explicit
destructor "call" but it doesn't say how that is accomplished.
Frankly, as I was trying to point out originally, destructors
don't strictly overload like a regular function if for no other
reason, than the name of the function is DIFFERENT in the derived
class than it is in the base class.

There has to be special magic in the call of a destructor.
The virtual declaration of the base class destructor tells
the compiler that additional magic must be required.

Frankly, it could have been that the compiler ALWAYS did the
right thing regardless of whether the destructor was declared
virtual or not, or it relied on whether the class was polymorphic
in general, but since VIRTUAL wasn't being used on destructors
anyhow AND the fact that there is a heavy "DON'T ENCUMBER THE
PERFORMANCE WITH ANYTHING THE PROGRAMMER DOESN'T EXPLICITLY
DECLARES HE NEEDS" mindset in C++, causes the stanard to use
virtual as a flag that polymorphic delete might happen.

Adam H. Peterson

unread,
Jun 13, 2002, 12:34:14 PM6/13/02
to
<snip>

> Frankly, as I was trying to point out originally, destructors
> don't strictly overload like a regular function if for no other
> reason, than the name of the function is DIFFERENT in the derived
> class than it is in the base class.

Just to add, another way destructors are different is that they ensure the
base version is invoked after the body of the derived. Normal virtual
functions completely replace the behavior of the base, unless the programmer
explicitly calls the base.


Alexander Terekhov

unread,
Jun 13, 2002, 2:22:07 PM6/13/02
to

That's OK/fine [lack of rather useful pre-destructors aside ;-)], but my
question was basically why the polymorphic behavior [and arrays] was simply
'ignored' by the standard writers w.r.t. *placement non-std::nothrow_t stuff*
and they simply decided to 'throw it' on us -- 'application' programmers.

regards,
alexander.

Alexander Terekhov

unread,
Jun 13, 2002, 2:43:22 PM6/13/02
to

Ooops, polymorphic behavior works:

struct B {
virtual ~B() { }
};

struct D : B {
~D() { }
};

D D_object;
typedef B B_alias;
B* B_ptr = &D_object;

void f() {
D_object.B::~B(); // calls B's destructor
B_ptr->~B(); // calls D's destructor
B_ptr->~B_alias(); // calls D's destructor
B_ptr->B_alias::~B(); // calls B's destructor
B_ptr->B_alias::~B_alias(); // error, no B_alias in class B
}

but arrays/'automatic'/non-manual-invocations don't.

Or am I again missing something? ;-)

regards,
alexander.

josh

unread,
Jun 13, 2002, 2:27:41 PM6/13/02
to
On Thu, 13 Jun 2002 09:38:18 -0400, Ron Natalie
<r...@sensor.com> wrote:
> josh wrote:
> > That is *always* the case, whether the destructor is
> > virtual or not, the problem is to start with the destructor
> > of the actual class of the physical object rather than with
> > the class that the pointer happens to be declared to point
> > to.
>
> You are assuming that all the destruction logic is
> implemented in the destructor calling sequence. There is
> nothing in the C++ language that guarantees this.
Well, that's a good point. Do you (or anyone reading, actually)
know what the practical situation here is? Is that a reasnable
assumption or not? (Forget the standard for a moment.)


> > If the pointer
> > is declared to point to a base class, in the case of a non-
> > virtual destructor, this base class's destructor will be
> > called
> > (I'm not sure about undefined behaviour here), not the
> > destructor of the derived class that the pointer in
> > question actually points to.
>
> Why don't you come back when you are sure. You are wrong.
> It is outright undefined behavior. Perhaps in the tiny
> examples you've tried all you get is the wrong destructor.
> Try putting some allocation functions (operator new/delete)
> in these classes. I guarantee you will see more untoward
> behavior.

Will do, that is an interesting thing to try. Would you have
any specific code examples of "untoward behavour" in that
context? No sarcasm, just asking.


> > Partially correct, but that wasn't the question. The
> > question is how the call is dispatched, not what happens
> > after the dispatched-to function/destructor is entered
> > (which doesn't have anything to do with how the function
> > was reached -- via a pointer or whatever; once you've
> > entered the function the
> > question of virtualness is out of the picture.)
>
> None of which you claim as 'truth' is mandated by the C++
> standard. You can not make these statements about the way
> things are invoked.

Well, that again is true. Actually I simply don't know what the
standard mandates in the respect, thus my question.

> Yes, I'm sure.
That is an aswer! Thank you.

> Even you should be able to see this in your
> warped assumptions about how the destructors work. How is
> the virtual call to the derived destructor going to work, if
> the base class virtual funcction isn't virtual.

This thing doesn't make a lot of sense. "the base class virtual
funcction isn't virtual." What's that supposed to mean.

If you meant to say that the base class doesn't have a virtual
destructor (?) then obviously the call to it will not be
virtual. Maybe it'll be the same as a call to a class w/o any
virtual members? Don't know. While Stroustroup (and Koenig) do
not explicitly say what the standard stipulates, both sort of
suggest that you need to make destructors virtual to hit the
right one (in my precise words), and Koenig actually goes
(p.40):

struct B { String s: };
struct D: B { String t: };

int main()
{
B* bp = new D; // not problem here, but...
delete bp; // this calls the wrong destructor unless
// B has a virtual destructor!
}

OK, I can, sort of, allow that the stress here can be on how to
achieve correct behaviour rather than specify in the most
legalistic detail what will happen if you don't. But still,
that's what it says.

Also, I'm not sure if that was clear: I'm not trying to
disprove that it's undefined. I'm just thinking around this
issue, that's all. So, please wind down a bit if you feel like
commenting, or just don't comment at all, you're not obligated,
after all. The whole "undefined" issue is an accidental side-
line to the original question, brought on by your own comments!
Iow, I'll gladly consider whatever you choose to offer, but I'm
not insterested in a flame war.

> It's the same with any function:
>
> struct Base {
> void Function();
> };
> struct Derived : Base {
> virtual void Function();
> };
>
> Base* bp = new Derived;
>
> bp->Function(); // still calls Base::Function(), it's
> not virtual

What is that supposed to demonstrate? Anything undefined here?
Make "Function" a destructor, won't it be what I'm saying all
along?

josh

unread,
Jun 13, 2002, 2:36:00 PM6/13/02
to
On Thu, 13 Jun 2002 02:57:31 -0700, David Schwartz
<dav...@webmaster.com> wrote:
> josh wrote:
> >
> > On Wed, 12 Jun 2002 21:26:01 -0400, Pete Becker
> > <peteb...@acm.org> wrote:
> > > josh wrote:
> > > >
> > > > but is it undefined *which* destructor will be called
> > > > (regardless of the results of calling it, that is)?
> > > >
> > >
> > > The behavior is undefined. End of sentence.
> > If that's all you can add to the topic, please kindly fuck
off.
> > End of sentence.
>
> He is right. If it's undefined, it's undefined.
> Anything can happen.
I'm not trying to prove otherwise.

David White

unread,
Jun 13, 2002, 7:48:10 PM6/13/02
to
josh <jo...@xtreme.net> wrote in message
news:1104_1023928610@l2092in-wllka-2...

Since people keep pronouncing that it's undefined, I thought it would be
helpful to give what looks like the relevant part of the standard.

Section 5.3.5 Delete

3 In the first alternative (delete object), if the static type of the
operand is different from its dynamic type, the static type shall be a
base class of the operand's dynamic type and the static type shall
have a virtual destructor or the behavior is undefined. In the second
alternative (delete array) if the dynamic type of the object to be
deleted differs from its static type, the behavior is undefined.19)

David

Ron Natalie

unread,
Jun 13, 2002, 8:16:14 PM6/13/02
to

josh wrote:

> Well, that's a good point. Do you (or anyone reading, actually)
> know what the practical situation here is? Is that a reasnable
> assumption or not? (Forget the standard for a moment.)

It's wrong in theory and practice.

>
> Will do, that is an interesting thing to try. Would you have
> any specific code examples of "untoward behavour" in that
> context? No sarcasm, just asking.

The untoward behavior is that the wrong operator delete gets called.
This will be very bad.

> delete bp; // this calls the wrong destructor unless
> // B has a virtual destructor!

The comment is technically wrong. Andy will agree (he's around
here somewhere).

> Also, I'm not sure if that was clear: I'm not trying to
> disprove that it's undefined. I'm just thinking around this
> issue, that's all.

Thinking around what? In practice you know of one form of
the undefined behavior which is bad enough (the wrong destructor
gets called). I've demonstrated another (wrong operator delete).
The standard doesn't bound the problem. The compiler is free
to base all kinds of decisions on polymorhphic delete on the
fact that the virtual destructor is flagged.


> So, please wind down a bit if you feel like
> commenting,

People wouldn't get so annoyed at you if you didn't argue with
the wrong answers (which you admit that you haven't bothered
to read the essential materials). For those of us who have
read the standard extensively, it's annoying to have posts
that say "are you sure?"

David White

unread,
Jun 13, 2002, 8:23:40 PM6/13/02
to
josh <jo...@xtreme.net> wrote in message
news:1103_1023992861@l2092in-wllka-2...

> On Thu, 13 Jun 2002 09:38:18 -0400, Ron Natalie
> <r...@sensor.com> wrote:

> > Why don't you come back when you are sure. You are wrong.
> > It is outright undefined behavior. Perhaps in the tiny
> > examples you've tried all you get is the wrong destructor.
> > Try putting some allocation functions (operator new/delete)
> > in these classes. I guarantee you will see more untoward
> > behavior.

> Will do, that is an interesting thing to try. Would you have
> any specific code examples of "untoward behavour" in that
> context? No sarcasm, just asking.

Here's what the standard says:

12.5 Free store

8 When a delete-expression deallocates an object whose static type has a
virtual destructor, it invokes the non-placement operator delete, if
any, that is a member of the object's dynamic type. [Note: if it
exists, that non-placement operator delete was found by the lookup at
the definition of the dynamic type's virtual destructor
(_class.dtor_). ] If no such member operator delete exists, the
delete-expression calls the global deallocation function
(_basic.stc.dynamic.deallocation_). Otherwise, the static and dynamic
types of the object shall be identical and the deallocation function
to be called is determined by looking up the name of operator delete
in the scope of the class that is the static type of the object.2) If
the result of the lookup is ambiguous or inaccessible, the program is
ill-formed. If no deallocation function is found in that scope, the
global deallocation function (_basic.stc.dynamic.deallocation_) is
used; see _expr.delete_.

I think what this amounts to regarding your question is that there's nothing
preventing you having a completely different memory allocator in each
derived class, and that the wrong operator delete (i.e., one that uses an
allocator/deallocator different from that used by the 'new' expression) will
probably be called if you don't have a virtual destructor.

struct B
{
~B();
void *operator new(size_t);
void operator delete(void *);
};

struct D : public B
{
void *operator new(size_t); // different allocator from that used by B
void operator delete(void *);
};

void f()
{
B *pb = new D;
delete pb; // big trouble
};

Of course, as has been mentioned ad nauseum, the behaviour of the delete is
undefined regardless of the operator news and deletes, but on a real
compiler you might need something like this to see it fail.

David

josh

unread,
Jun 13, 2002, 3:50:08 PM6/13/02
to
On Thu, 13 Jun 2002 20:16:14 -0400, Ron Natalie
<r...@sensor.com> wrote:
> People wouldn't get so annoyed at you if you didn't argue
> with the wrong answers
I didn't bring the "undefined" issue in, that was your own
comment (very lateral to the topic.) The thread started with
the question about virtual vs regular destructors, and my
comment was, in short, that one makes a destructor virtial in
order to hit the right one when called via a base pointer, and
that it's the same here as it is with virtual functions. There
are no "wrong answers" here at all.

You're a kind of guy who, if I said to someone that you address
parcels by writing the address on them, and that it's the same
as with letters, you'd barge in, fuming that parcels and
letters are not the same. Well, OK.

0 new messages