Topic: Should we do a public derivation from a base class withoutvirtual destructor ?
Author: "Thomas W. Brown" <tbrown@softbook.com>
Date: 1999/08/18 Raw View
Ron Natalie wrote:
>
> Waranun Bunjongsat wrote:
> >
> > Except in the industries where people are paranoid about
> > any situation, which can cause damages. You may get laid off if the
> > customers deleted your derived class from its base class pointer whose
> > class do not have virtual destruction, and it resulted in major and
> > frequent crashes of the system, which are found out later; after the
> > customers already delivered their product to their major customer or
>
> If you persist in writing code that becomes a support and maintenance
> nightmare because you insist on relying on undefined behavior, you
> won't last long in my company whether the product is one of our
> medical products or a little image display program for the remote
> sensing product.
I don't think anyone is insisting on relying on undefined behavior just
because we like the way the code looks or anything. Rather we are (I
am, at least) trying to reconcile the following:
A quite general blanket statement that public derivation from a class
with a non-virtual destructor causes undefined behavior if an object of
the derived class is deleted from a pointer to base class.
-and-
The notion of a derived class that adds only "plain" functions; no
destructor, no virtual functions, no data members; and whether such a
class, derived via public inheritance from a class with a non-virtual
destructor really, by itself, will have undefined behavior.
-- Thomas Brown
tbrown@softbook.com
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: clamage@eng.sun.com (Steve Clamage)
Date: 1999/08/18 Raw View
"Thomas W. Brown" <tbrown@softbook.com> writes:
>I don't think anyone is insisting on relying on undefined behavior just
>because we like the way the code looks or anything. Rather we are (I
>am, at least) trying to reconcile the following:
>A quite general blanket statement that public derivation from a class
>with a non-virtual destructor causes undefined behavior if an object of
>the derived class is deleted from a pointer to base class.
That is what the C++ standard says. It does not require
implementations to let your code work the way you want.
>-and-
>The notion of a derived class that adds only "plain" functions; no
>destructor, no virtual functions, no data members; and whether such a
>class, derived via public inheritance from a class with a non-virtual
>destructor really, by itself, will have undefined behavior.
Well, there is no such thing as a class without a destructor.
The compiler writes one for you if you don't declare one.
But the result still depends on the implementation. For one
thing, you haven't covered all the bases. Example:
class Base { ..... }; // no virtual destructor
class Derived : public Base { // no data, no virtual functions
public:
void* operator new(size_t);
void operator delete(void*);
};
Base *p = new Derived;
delete p; // Boom!
The global operator delete will (most likely) be called instead
of Derived::operator delete. I say "most likely" because that
is the behavior that falls out of typical implementations --
the results are undefined by the standard.
The short answer is that if you want polymorphic behavior
(and deleting an object via a base-class pointer is asking
for polymorphic behavior), use virtual destructors.
If you don't want polymorphic behavior, consider whether
derivation is an appropriate model. For example, maybe
you should do this instead:
class Derived { // no base classes
public:
Base b; // member, instead of base class
...
};
--
Steve Clamage, stephen.clamage@sun.com
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: postmast.root.admi.gov@iname.com (blargg)
Date: 1999/08/19 Raw View
In article <37BB1CC8.6D5FDF06@softbook.com>, "Thomas W. Brown"
<tbrown@softbook.com> wrote:
> Ron Natalie wrote:
> >
> > Waranun Bunjongsat wrote:
> > >
> > > Except in the industries where people are paranoid about
> > > any situation, which can cause damages. You may get laid off if the
> > > customers deleted your derived class from its base class pointer whose
> > > class do not have virtual destruction, and it resulted in major and
> > > frequent crashes of the system, which are found out later; after the
> > > customers already delivered their product to their major customer or
I can't imagine any place that such code would be OK, except for writing
intentionally-buggy software (job security, etc. :-). We sure don't need
more crap software these days in *any* field.
> > If you persist in writing code that becomes a support and maintenance
> > nightmare because you insist on relying on undefined behavior, you
> > won't last long in my company whether the product is one of our
> > medical products or a little image display program for the remote
> > sensing product.
I can feel the tension! :-)
> I don't think anyone is insisting on relying on undefined behavior just
> because we like the way the code looks or anything. Rather we are (I
> am, at least) trying to reconcile the following:
>
> A quite general blanket statement that public derivation from a class
> with a non-virtual destructor causes undefined behavior if an object of
> the derived class is deleted from a pointer to base class.
One reason being that the original block of memory couldn't necessarily be
recovered for deletion:
struct X { int i; };
struct Y { int j; };
struct Z : X, Y { };
void del( Y* p ) {
delete p; // how does it know how to recover the original memory?
}
void f() {
del( new Z );
del( new Y );
}
In many implementations, the bit pattern for the pointer to the Y
sub-object of the Z object created will be different than the bit pattern
for the pointer to the Z object.
To enumerate all the cases where delete would work would be significantly
more complex even for a specific implementation of base classes. For other
implementations, I suspect that undefined really is bad, in that no
deletion through a base class pointer would yield usable run-time results.
> The notion of a derived class that adds only "plain" functions; no
> destructor, no virtual functions, no data members; and whether such a
> class, derived via public inheritance from a class with a non-virtual
> destructor really, by itself, will have undefined behavior.
The question wouldn't "will it have undefined behavior", but "would it be
reasonable to require that this have defined behavior (with regards to
implementors)".
I'm trying to figure out where such a class would be useful, and ways of
achieving the same thing with the current language definition.
Any added operations could be made free functions that took the original
type as an argument. This would allow them to be used on the original
type, instead of just the original derived type. I can't think of any way
of establishing any invariants on the derived type if it used public
derivation, since those could be broken by using the base class interface.
If public derivation wasn't used, it seems that it would be unlikely that
anyone would be deleting the object through the base class.
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Ron Natalie <ron@sensor.com>
Date: 1999/08/19 Raw View
Thomas W. Brown wrote:
>
> -and-
>
> The notion of a derived class that adds only "plain" functions; no
> destructor, no virtual functions, no data members; and whether such a
> class, derived via public inheritance from a class with a non-virtual
> destructor really, by itself, will have undefined behavior.
>
If you delete it through the base class pointer, it needs to
have a virtual destructor, otherwise not. The fact that the
implemenations you've used don't care is immaterial. There's
nothing that keeps a implmentation from relying on a virtual
destructor.
The dynamic memory of C++ is admittedly a crock hold over
from the abysmal C Malloc implementations. I don't defend
it, but you got to play by the rules if you're going to
use it.
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]