Topic: We should allow official suppressing of automatically defined (and


Author: hyrosen@mail.com (Hyman Rosen)
Date: Fri, 13 Aug 2004 21:06:05 GMT
Raw View
John Nagle wrote:
>     If you delete a pointer to a Base, "~Derived" will
> not be called. That's not safe.

You cannot do this, because the Base destructor is protected.

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: sarima@friesen.net (Stanley Friesen)
Date: Mon, 9 Aug 2004 00:44:49 GMT
Raw View
nagle@animats.com (John Nagle) wrote:

>Bob Bell wrote:
>> nagle@animats.com (John Nagle) wrote in message news:<ib9Qc.477$nz1.48@newssvr27.news.prodigy.com>...
>>>     Define an "empty destructor" as a default destructor for a class
>>>which contains no data members with non-empty destructors.  An
>>>"empty destructor" doesn't do anything to the object before
>>>its space is released.
>>
>> Let's see if I can post only once this time. ;-)
>>
>> Except that when you have a base class with a non-virtual empty
>> destructor, and a derived class with a non-empty destructor, and an
>> object of the derived class is destroyed through a pointer to the base
>> class, you still have undefined behavior. So you end up disallowing
>> some legitimate uses of inheritance while not actually preventing the
>> problems from occurring.
>
>    True.
>
>    So correctness requires that, if you have a non-virtual destructor
>in a base class, you can't have a non-empty destructor in a class
>derived from it.
>
Even that isn't sufficient.  The derived class must also be the same
*size* as the base class, since in the absence of virtual destructor the
implementation is allowed to assume the size of the object being
deleted.

>    That's probably a liveable restriction.  The two most common
>reasons for wanting to avoid a virtual destructor are
>
>    1. The class is a POD (Plain Old Data), and you don't want
> the vtable overhead.
>
>    2. The base class has a non-virtual destructor and wasn't
> designed to be subclassed, but you want to subclass it anyway.

In the latter case, you probably want to either use private inheritance,
or make sure all deallocation is done via a derived class pointer by
some other means.
>
>Case 1 is safe.
>
No it isn't.

--
The peace of God be with you.

Stanley Friesen

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: nagle@animats.com (John Nagle)
Date: Mon, 9 Aug 2004 04:21:51 GMT
Raw View
Lo=EFc Joly wrote:
> John Nagle wrote:
>=20
>>    So correctness requires that, if you have a non-virtual destructor
>> in a base class, you can't have a non-empty destructor in a class
>> derived from it.
>>
>>    That's probably a liveable restriction.  The two most common
>> reasons for wanting to avoid a virtual destructor are
>>
>>    1.    The class is a POD (Plain Old Data), and you don't want
>>     the vtable overhead.
>>
>>    2.    The base class has a non-virtual destructor and wasn't
>>     designed to be subclassed, but you want to subclass it anyway.
>>
>> Case 1 is safe.
>>
>> Case 2 is only safe if the derived class doesn't have a destructor.
>=20
>=20
> Why so ? Even if the derived class does not have a destructor, deleting=
=20
> a derived class through a pointer to the base class is still undefined=20
> behaviour if the base class does not have a virtual destructor.

    Sorry, by "doesn't have a destructor" I mean "doesn't have a
non-empty destructor".  All classes have an implicit destructor, of
course.

    It should be defined behavior to delete a class through the
base pointer provided that no derived class has a non-empty
destructor.  If that's allowed, and the case with a non-empty
destructor is disallowed at compile time, we get safety with
the ability to do the overriding that some people insist is
necessary.

> And even though I would appreciate a compiler that tells me about this=20
> case, I do not think this is enough to prevent derivation from a base=20
> class with no virtual destructor.

    You want a stronger restriction?

> The only safe case is when you do not use the class polymorphically, or=
=20
> when the specific compiler you use defines this undefined behavious (in=
=20
> which case, this code is not portable).
>=20
> One example of a legitimate use (at least, I have not found any solutio=
n=20
> that I would find better, the alternatives are just too much code to=20
> duplicate) is when you want to have a class that behaves just like a=20
> std::string, but write in a log file each time a string is created.
>=20
> You basically have four solutions :
> - use string by composition, and define in myString all string member=20
> functions, and implement them by forwarding the call to the embeded=20
> std::string.
> - derive privately from std::string, provide some converion operation t=
o=20
> std::string, and write a using clause for all member functions of=20
> std::string.
> - Make your own class unrelated to std::string and provide some=20
> conversion operations.
> - Publically derive from std::string, add the constructor, and you are=20
> done. Just tell the users not to use this class polymorphically.

    That's a good argument that std::string should have a
virtual destructor.  Or that the proposal I made above
should be accepted.

    John Nagle
    Animats

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Wed, 4 Aug 2004 19:48:49 GMT
Raw View
John Nagle wrote:
>     If you're overriding a destructor for a class that has a
> destructor that does something, the program does have a bug.
> A destructor that does something is being silently skipped.
> That should be caught at compile time.

No. This is not an error, and will break existing code.
It is perfectly OK to derive from a class which has a
non-virtual "does something" destructor, and to have a
"does something" destructor in the derived class.

The only time an error occurs is if an object of this
derived class is deleted through a pointer to the base
class. If the object is deleted through a pointer to
the derived class, or if an automatic object of the
derived type goes out of scope, the entire chain of
destructors is called properly.

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Thu, 5 Aug 2004 20:46:54 GMT
Raw View
John Nagle wrote:
>     That's easy to check for at run time.  If the size
> at "delete" doesn't match the proper size for the type,
> an error should be reported.

No. There is no reason that a derived type is any larger
than the base type. There is no reason that an alloactor
necessarily keeps track of the exact size of an allocated
block. That could be required, increasing the overhead for
small objects, and at that point you may as well store a
vtbl pointer in every object, making the whole issue moot.

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]