Topic: Compiler should generate virtual destructors


Author: ark@alice.att.com (Andrew Koenig)
Date: 22 Jan 93 13:01:52 GMT
Raw View
In article <harvey.727664973@regina> harvey@opl.com (Harvey Reed) writes:

> I like this! Compilers could have "compatibility" switches, but for
> those of us who would rather do it ourselves, we could use the
> full strength version.

The trouble with compatibility switches is that they force people
who care about portability to write in the intersection of the language
accepted in the two modes.
--
    --Andrew Koenig
      ark@europa.att.com




Author: reindorf@us-es.sel.de (Charles Reindorf)
Date: Sat, 23 Jan 93 08:16:16 GMT
Raw View
In article <lm0gudINN9be@exodus.Eng.Sun.COM>, chased@rbbb.Eng.Sun.COM (David Chase) writes:
|> In article <1993Jan22.081555.12027@us-es.sel.de> reindorf@us-es.sel.de (Charles Reindorf) writes:
|> >On the subject of "trampolenes" in the implementation of nested functions, this
|> >presumably means the following appraoch:
|>
|> > [code generation into stack frame, which works.]
|> > ... The main objection I can see is that on some operating systems
|> >you are not allowed to do any run-time code generation.
|>
|> One workaround is to keep a cache of trampolines, which in this case
|> are pairs of code+data, where each piece of code is compiled to
|> reference a particular piece of data.  Some run-time code generation
|> must still occur.  In the limit case (the least flexible OSes) a
|> different calling convention must be used for all function calls.

As you say, the cache appraoch still involves generating code on the fly,
or making the function pointer data type more complex (impacting all cases)
and changing the procedure call convention.
|>
|> >Other people talk about "bound" functions which presumably means that
|> >given an object a of class A with member function f, then "a.f" can be
|> >regarded as a new function (whose pointer can be taken) with a non
|> >member-function signature.  The only way I can see of using a
|> >trampolene appraoch for this situation is to place the trampolene for
|> >the function a.f into the object a itself.
|>
|> Actually, you could "new" them.  Just allocate the functions on the
|> "heap", and free them when you are done.  Or, we could take a flying
|> leap at the slippery slope and add garbage collection.

Again, as you say, you have to free them "when you are done", but in
this situation, there is no natural idea of "when you are done". In
fact, whereas the natural lifetime of a nested function is until the
containing function completes, the natural lifetime of a bound function
is until the destruction of the object to which it is bound. How do you
ensure that whenever an object dies, that bound function trampolenes
which *might* have been generated for it are deleted? (Bearing in mind
that the object may not otherwise need any destructor and may not have
any virtual functions at all).

|> >This surely makes member function closures an impracticable and
|> >unworkable addition to the language?
|>
|> I think the answer is another question: "compared to what?"  I'm
|> really looking forward to run-time instantiation of templates.

I can see no way that the solution can be implemented in a way that
doen't impact the normal performance of the system. The only way I
can see round this is to add something to the syntax of the language
to indicate "this member function might be bound" at the point of
declaration. To me, this is unacceptable.

None of this detracts from the fact that *nested* functions *can* be
implemented without impacting on the normal performance of the system,
and without requiring any special new constructs in the language (more
a relaxation of a rule). What's more, they are extremely valid for
situations where iterators are used for many general call-back
mechanisms which are considerably more awkward (or unsafe) when done
using one of the manual alternatives.

Moreover, if nested functions are implemented, they imply an easy
manual solution to many cases where bound member functions might have
been required. Other cases where bound member functions might be
required can surely be solved through abstract base classes and in some
cases MI.

|>
|> David Chase
|> Sun






Author: harvey@opl.com (Harvey Reed)
Date: 25 Jan 93 16:21:54 GMT
Raw View
ark@alice.att.com (Andrew Koenig) writes:

>In article <harvey.727664973@regina> harvey@opl.com (Harvey Reed) writes:

>> I like this! Compilers could have "compatibility" switches, but for
>> those of us who would rather do it ourselves, we could use the
>> full strength version.

>The trouble with compatibility switches is that they force people
>who care about portability to write in the intersection of the language
>accepted in the two modes.

Would this apply if the "compatibility mode" was phased out over time?
In a similar manner to how C vendors gradually migrated to ANSI C?



--
++harvey
===========================================================================
internet:       harvey@opl.com  /  hreed@cs.ulowell.edu  /  h.reed@ieee.org
voice/fax:      617-965-0220    /  617-965-7599




Author: ark@alice.att.com (Andrew Koenig)
Date: 25 Jan 93 21:23:36 GMT
Raw View
In article <harvey.727978914@regina> harvey@opl.com (Harvey Reed) writes:

> Would this apply if the "compatibility mode" was phased out over time?
> In a similar manner to how C vendors gradually migrated to ANSI C?

Yes.  While the "compatibility mode" is being phased out, I still
have to write in the intersection of the two languages, until the
old one is well and truly gone.
--
    --Andrew Koenig
      ark@europa.att.com




Author: maxtal@extro.ucc.su.OZ.AU (John MAX Skaller)
Date: 26 Jan 93 22:54:09 GMT
Raw View
In article <1993Jan23.081616.29910@us-es.sel.de> reindorf@us-es.sel.de (Charles Reindorf) writes:
>|> Actually, you could "new" them.  Just allocate the functions on the
>|> "heap", and free them when you are done.  Or, we could take a flying
>|> leap at the slippery slope and add garbage collection.
>
>Again, as you say, you have to free them "when you are done", but in
>this situation, there is no natural idea of "when you are done". In
>fact, whereas the natural lifetime of a nested function is until the
>containing function completes, the natural lifetime of a bound function
>is until the destruction of the object to which it is bound. How do you
>ensure that whenever an object dies, that bound function trampolenes
>which *might* have been generated for it are deleted?

 The compiler doesn't bother to try. Leave it up to the programmer.
Nothing new here :-) After all, just killing the trampoline doesn't stop
you calling it through the pointer you still have lying around.

>I can see no way that the solution can be implemented in a way that
>doen't impact the normal performance of the system.

 Just leave deletion of the trampoline up to the programmer
like all other dynamically created objects.

>
>None of this detracts from the fact that *nested* functions *can* be
>implemented without impacting on the normal performance of the system,
>and without requiring any special new constructs in the language (more
>a relaxation of a rule). What's more, they are extremely valid for
>situations where iterators are used for many general call-back
>mechanisms which are considerably more awkward (or unsafe) when done
>using one of the manual alternatives.

 Yes, callbacks are a compelling argument. Must
remember this for the proposal.
>
>Moreover, if nested functions are implemented, they imply an easy
>manual solution to many cases where bound member functions might have
>been required. Other cases where bound member functions might be
>required can surely be solved through abstract base classes and in some
>cases MI.

 But the bound members can be had easily
IF we have trampolines for the nested functions, without
any more loss of safety than you get with ordinary pointers.
(Although the effects of executing non-existant code,
or existant code for non-existant objects will be nasty,
if you dont like it --- dont use it)

--
;----------------------------------------------------------------------
        JOHN (MAX) SKALLER,         maxtal@extro.ucc.su.oz.au
 Maxtal Pty Ltd, 6 MacKay St ASHFIELD, NSW 2131, AUSTRALIA
;------ SCIENTIFIC AND ENGINEERING SOFTWARE ---ph:  2 799 8223 --------




Author: dcb@slsveit (David Binderman (SWP))
Date: Thu, 28 Jan 93 09:50:59 GMT
Raw View
David Brownell (db@argon.Eng.Sun.COM) wrote:
: On the other hand, one of the things I'd really like to see changed is
: how much stuff a C++ compiler does "for me" automagically.  It's a rare

Agreed. What the C++ compiler does is a constant source of bugs.

: So, a pair of proposals that I'd be happier to see accepted:

:    (1) It is an error for a class to have virtual functions and a
:  nonvirtual destructor.

I'd vote for it being a warning. Then compilers can be graded on their
user friendliness.

:
:    (2a) C++ compilers don't automagically generate ANYTHING for classes
:  any more:  constructors, destructors, assignment and address-of
:  operators, etc.  If such routines are used but not declared and
:  defined, that is an error.

Agree 100%. Also, any compiler that implements a warning for a class which
only declares one or two of the (ctor, dtor, copy ctor) set would get my vote.

The C++ FAQ has other suggestions for a C++ lint to do.

Also, drop all this "struct is a class with different visibility". Our
programmers here have spent years learning what a C struct is. Don't change
it. Just make the restriction that any struct which defines a method
must be converted into a class. It makes life simple: a C++ struct can
only define data, and the moment it declares a method, then it
must be a class.

I'd also vote for any compiler which produced a warning for an inline method
definition

class K {
 void f() { // no !
 };
..
};

And another warning the compiler implementers out there might consider
is that if a constructor calls new, and the matching destructor does
not, then I want to see a warning for that destructor.

But hey, all this talk of improving the details of the compiler
implementation fails to address the real problem: The ARM has been
publically available for nearly three years now, and I have yet to see
a compiler which implements the ARM ( less Exceptions and Templates
obviously). Ok I will be able to use the full functionality of the ARM
when (if ?) the moment it arrives, but I can't even get a compiler
for a reasonable language subset.

I'm sure the reason for this is the complexity of the language.
Me, I'd vote for Typesafe ANSI C with Objects thrown in.
No inheritance, no virtual functions, no polymorphism. The rest is hard
for the compilers to implement, hard for the programmers to understand,
and hard to build reliable systems that work using those features.

Regards
--
David C Binderman     Dept US/ESI, Bau 60, SEL-Alcatel AG, Lorenz Strasse 10,
D-7000 Stuttgart 40, Germany      dcb@us-es.sel.de   Tel: +49 711 821 3841




Author: harvey@opl.com (Harvey Reed)
Date: 22 Jan 93 01:09:33 GMT
Raw View
db@argon.Eng.Sun.COM (David Brownell) writes:

>...
>So, a pair of proposals that I'd be happier to see accepted:

>   (1) It is an error for a class to have virtual functions and a
> nonvirtual destructor.
>
>   (2a) C++ compilers don't automagically generate ANYTHING for classes
> any more:  constructors, destructors, assignment and address-of
> operators, etc.  If such routines are used but not declared and
> defined, that is an error.


I like this! Compilers could have "compatibility" switches, but for
those of us who would rather do it ourselves, we could use the
full strength version.

I think I would feel a lot better about my C++ compiler if I didn't
have to make a copy-ctor private/unimplemented (as a safegaurd) just
because I was afraid that I *might* be accidentally copying an object.
It would be much better if the compiler simply said it was an error
to copy without a copy-ctor (or whatever), then the programmer can:

1) remove the need to copy
2) install the proper method to do the copy

This goes for all the other automagic stuff too! I cringe when I
think about automagically adding virtual destructors, even though
they are most times needed...



--
++harvey
===========================================================================
internet:       harvey@opl.com  /  hreed@cs.ulowell.edu  /  h.reed@ieee.org
voice/fax:      617-965-0220    /  617-965-7599




Author: pjl@cs.uiuc.edu (Paul Lucas)
Date: Fri, 22 Jan 1993 12:13:53 GMT
Raw View
In <harvey.727664973@regina> harvey@opl.com (Harvey Reed) writes:

>db@argon.Eng.Sun.COM (David Brownell) writes:

>>...
>>So, a pair of proposals that I'd be happier to see accepted:

>>   (1) It is an error for a class to have virtual functions and a
>> nonvirtual destructor.

 A warning, perhaps.

>>   (2a) C++ compilers don't automagically generate ANYTHING for classes
>> any more:  constructors, destructors, assignment and address-of
>> operators, etc.  If such routines are used but not declared and
>> defined, that is an error.

 Would break a large part of th the world (like all struct declarations
 for starters; see below).

>I think I would feel a lot better about my C++ compiler if I didn't
>have to make a copy-ctor private/unimplemented (as a safegaurd) just
>because I was afraid that I *might* be accidentally copying an object.
>It would be much better if the compiler simply said it was an error
>to copy without a copy-ctor (or whatever), then the programmer can:

>1) remove the need to copy
>2) install the proper method to do the copy

>This goes for all the other automagic stuff too! I cringe when I
>think about automagically adding virtual destructors, even though
>they are most times needed...

 Another case for protecting programmers from themselves.  For:

  struct Point {
   int x, y;
  };

 I don't want to have to write a ctor and assign-op. especially
 when the generated ones would work perfectly.

 Whenerver one writes a class, one *has* to ask onesself: Do I
 need a ctor?  An assign-op?  One should have to ask onesself
 this regardless of whether the compiler did the default ones
 for one or not.  If one doesn't, then one is just careless.

 The default stuff is for convenience.  In my experience, and I
 would venture others', it's rare to have to forbid copy/assign
 anyway.  Unless you have a good reason to forbid them, who cares?
 Let users copy them.
--
 - Paul J. Lucas
   AT&T Bell Laboratories
   Naperville, IL




Author: db@argon.Eng.Sun.COM (David Brownell)
Date: 2 Jan 1993 21:35:03 GMT
Raw View
maxtal@extro.ucc.su.OZ.AU (John MAX Skaller) writes:

> I would like to propose that if a class has virtual functions,
> then any destructor generated by the compiler will be virtual
> by default.

Hmmm ... given that I've never seen such nonvirtual destructors be
anything except bug, I like the idea of fixing this problem.

On the other hand, one of the things I'd really like to see changed is
how much stuff a C++ compiler does "for me" automagically.  It's a rare
day when it really does what I need to have done; just how often is
memory management broken when pointers "owned" by class instances are
bitwise copied?  Arguments I've heard against automagic generation of
code by the C++ compiler seem to fall into three categories:

    - Memory management bugs get trivially introduced, both in the
 initial implementations and during subsequent maintainence;

    - Declaring automagic routines as 'private', with implementations
 that abort, to prevent assigning/copying data structures that
 shouldn't be support those operations (due to various expenses,
 or to design desiderata) is really ugly, and consumes both
 coding and runtime resources;

    - It's confusing both to beginning and to expert programmers
 (e.g. C ones who are "upgrading" to C++) that private data
 structures be manipulated (and bugs added) by compilers.

So, a pair of proposals that I'd be happier to see accepted:

   (1) It is an error for a class to have virtual functions and a
 nonvirtual destructor.

   (2a) C++ compilers don't automagically generate ANYTHING for classes
 any more:  constructors, destructors, assignment and address-of
 operators, etc.  If such routines are used but not declared and
 defined, that is an error.

Or in short, if you want to allow copying, destruction, assignment,
and so on for instances of your classes, you'll have to explicitly
provide member functions to support those actions in the interface
definitions (and implementation bodies) for your classes.

Perhaps the specific issues with memory management could be fixed by
the alternate proposal below:

   (2b) C++ compilers don't automagically generate those routines
 (complete list omitted :-) for classes that have members which
 are pointers or references.  If such routines are used but
 not declared and defined, that is an error.

Existing code compiled with a compiler enforcing (2a) or (2b) would
generate error messages; fixing that code and then recompiling it with
today's compilers (e.g. CFRONT) would not cause any problems at all.

Comments?

- Dave

--
David Brownell                        db@Eng.Sun.COM.
Distributed Object Management





Author: maxtal@extro.ucc.su.OZ.AU (John MAX Skaller)
Date: Sun, 3 Jan 1993 03:10:32 GMT
Raw View
In article <9300301.307@mulga.cs.mu.OZ.AU> fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON) writes:
>maxtal@extro.ucc.su.OZ.AU (John MAX Skaller) writes:
>
>>I would like to propose that if a class has virtual functions,
>>then any destructor generated by the compiler will be virtual
>>by default.
>>
>>Advantages: much safer, ensures correct deletion of objects
>>by default.  Removes a source of bugs. Removes the reminder
>>that its wise to do this from the FAQ.
>>
>>Disadvantage: might slow down destruction a little. Can be
>>fixed by the programmer explicitly declaring a non-virtual
>>destructor.
>
>I think that this situation should cause a compiler warning, rather
>than adding another arbitrary rule in the language for programmers to
>remember.

 What arbitrary rule? Do you mean the rule that says
automatically generated destructors are *non-virtual* :-) ??

 The point here is that the forgetful programmer is protected.

>[Off the topic, another situation that should have a required warning
>is the (void *) to (T *) conversion.


 void *x;
 T* t;
 t=x; // error here, no mere warning
 t=(T*)x; // warning inserted by programmer in the form of (T*)
 t=reinterpret_cast<T*>x; // grepable warning

--
;----------------------------------------------------------------------
        JOHN (MAX) SKALLER,         maxtal@extro.ucc.su.oz.au
 Maxtal Pty Ltd, 6 MacKay St ASHFIELD, NSW 2131, AUSTRALIA
;--------------- SCIENTIFIC AND ENGINEERING SOFTWARE ------------------




Author: maxtal@extro.ucc.su.OZ.AU (John MAX Skaller)
Date: Sun, 3 Jan 1993 03:22:28 GMT
Raw View
In article <lkc2k7INNajv@exodus.Eng.Sun.COM> db@argon.Eng.Sun.COM (David Brownell) writes:
>maxtal@extro.ucc.su.OZ.AU (John MAX Skaller) writes:
>
>> I would like to propose that if a class has virtual functions,
>> then any destructor generated by the compiler will be virtual
>> by default.
>
>Hmmm ... given that I've never seen such nonvirtual destructors be
>anything except bug, I like the idea of fixing this problem.
>
>On the other hand, one of the things I'd really like to see changed is
>how much stuff a C++ compiler does "for me" automagically.  It's a rare
>day when it really does what I need to have done; just how often is
>memory management broken when pointers "owned" by class instances are
>bitwise copied?

 A decent solution could have been had except for the
extremely unfortunate (IMHO) decision that 'struct' and 'class'
are synonymous (except for public/private defaults).

 For example, how about:

 generate X::X(const X&);

This could only apply to classes and not 'C' structs for compatibility
reasons.

>
>So, a pair of proposals that I'd be happier to see accepted:
>
>   (1) It is an error for a class to have virtual functions and a
> nonvirtual destructor.
>
>   (2a) C++ compilers don't automagically generate ANYTHING for classes
> any more:  constructors, destructors, assignment and address-of
> operators, etc.  If such routines are used but not declared and
> defined, that is an error.

 Not possible for C-Structs, compiler MUST automagiocally
generate constructors and assignment for these.

 Want to modify (2a) to include 'with virtual functions'?

>
>Or in short, if you want to allow copying, destruction, assignment,
>and so on for instances of your classes, you'll have to explicitly
>provide member functions to support those actions in the interface
>definitions (and implementation bodies) for your classes.

 You do NOT want to have to write the code. Explicit
direction to the compiler to generate the code may be acceptable.

 generate X& operator=(const X&);

>
>Perhaps the specific issues with memory management could be fixed by
>the alternate proposal below:
>
>   (2b) C++ compilers don't automagically generate those routines
> (complete list omitted :-) for classes that have members which
> are pointers or references.  If such routines are used but
> not declared and defined, that is an error.

 Not compatible with C.

 Personally, I'd like to ban virtual functions from
'structs' and insist structs worked as they do in C.
Also allows nested structs to be globally visible, as in C.

 The classes could be distinct and have different rules.
But it is too late for this.

--
;----------------------------------------------------------------------
        JOHN (MAX) SKALLER,         maxtal@extro.ucc.su.oz.au
 Maxtal Pty Ltd, 6 MacKay St ASHFIELD, NSW 2131, AUSTRALIA
;--------------- SCIENTIFIC AND ENGINEERING SOFTWARE ------------------




Author: dpg@extro.ucc.su.OZ.AU (D P Gilbert)
Date: Sun, 3 Jan 1993 12:06:25 GMT
Raw View
maxtal@extro.ucc.su.OZ.AU (John MAX Skaller) writes:

>In article <lkc2k7INNajv@exodus.Eng.Sun.COM> db@argon.Eng.Sun.COM (David Brownell) writes:
>>maxtal@extro.ucc.su.OZ.AU (John MAX Skaller) writes:
>>
>>> I would like to propose that if a class has virtual functions,
>>> then any destructor generated by the compiler will be virtual
>>> by default.
>>
>>Hmmm ... given that I've never seen such nonvirtual destructors be
>>anything except bug, I like the idea of fixing this problem.
>>
>>On the other hand, one of the things I'd really like to see changed is
>>how much stuff a C++ compiler does "for me" automagically.  It's a rare
>>day when it really does what I need to have done; just how often is
>>memory management broken when pointers "owned" by class instances are
>>bitwise copied?

> A decent solution could have been had except for the
>extremely unfortunate (IMHO) decision that 'struct' and 'class'
>are synonymous (except for public/private defaults).

> For example, how about:

> generate X::X(const X&);

>This could only apply to classes and not 'C' structs for compatibility
>reasons.

>>
>>So, a pair of proposals that I'd be happier to see accepted:
>>
>>   (1) It is an error for a class to have virtual functions and a
>> nonvirtual destructor.
>>
>>   (2a) C++ compilers don't automagically generate ANYTHING for classes
>> any more:  constructors, destructors, assignment and address-of
>> operators, etc.  If such routines are used but not declared and
>> defined, that is an error.

> Not possible for C-Structs, compiler MUST automagiocally
>generate constructors and assignment for these.

>
>   Want to modify (2a) to include 'with virtual functions'?
> ......

How about a new keyword "__pure" to
 1) prefix "class" in a class definition to stop automagic
  constructor + assignment generation ++
 2) prefix "virtual" in a pure virtual function
  declaration to get rid of the "=0" hack
 3) waste some of the compiler implementor's name space
  (rather the the compiler user's name space). The
  user can #define pure __pure if it causes no problem


Doug Gilbert




Author: feathers@serss0 (Michael Feathers)
Date: 4 Jan 93 00:03:04 GMT
Raw View
In article <1992Dec31.050150.28929@ucc.su.OZ.AU> maxtal@extro.ucc.su.OZ.AU (John MAX Skaller) writes:
>I would like to propose that if a class has virtual functions,
>then any destructor generated by the compiler will be virtual
>by default.
>
>(The suggestion was first read by me in a paper of Markku Sakkinen,
>who claims it was not his idea originally either.)
>
>Advantages: much safer, ensures correct deletion of objects
>by default.  Removes a source of bugs. Removes the reminder
>that its wise to do this from the FAQ.

This would be a way in which a function within the source code would be
virtual without the keyword 'virtual' having been used on it or a function of
the same name in an inherited class.  That would bother me as a consistency
issue.

>Disadvantage: might slow down destruction a little. Can be
>fixed by the programmer explicitly declaring a non-virtual
>destructor.

The only way to make something explicity non-virtual would be the absence
of the 'virtual' keyword, unless we add a new keyword <shudder>.

If the destructor is going to be made virtual by that rule, there is no
need to declare it virtual.  But we can not make it explicitly non-virtual
unless the virtual keyword is an option.


Michael Feathers  [feathers@fiu.edu]      main () { main (); }




Author: hansen@myria.cs.umn.edu (David Hansen)
Date: Mon, 4 Jan 1993 00:30:54 GMT
Raw View
In article <C0Ayt4.263@fiu.edu>, feathers@serss0 (Michael Feathers) writes:
|> In article <1992Dec31.050150.28929@ucc.su.OZ.AU> maxtal@extro.ucc.su.OZ.AU (John MAX Skaller) writes:
|> >I would like to propose that if a class has virtual functions,
|> >then any destructor generated by the compiler will be virtual
                        ^^^^^^^^^^^^^^^^^^^^^^^^^
|> >by default.
|> >
[...]

|> This would be a way in which a function within the source code would be
|> virtual without the keyword 'virtual' having been used on it or a function of
|> the same name in an inherited class.  That would bother me as a consistency
|> issue.

I think you misread the original post.  Only the automagically generated
destructors would be virtual by default.  If the programmer explicity
defined a destructor _without_ the virtual keyword, it would not be virtual
(unless _I_ misread the post  :).

|>
|> >Disadvantage: might slow down destruction a little. Can be
|> >fixed by the programmer explicitly declaring a non-virtual
|> >destructor.
|>
|> The only way to make something explicity non-virtual would be the absence
|> of the 'virtual' keyword, unless we add a new keyword <shudder>.

Again, see comment above.

     -=Dave




Author: maxtal@extro.ucc.su.OZ.AU (John MAX Skaller)
Date: Mon, 4 Jan 1993 15:48:17 GMT
Raw View
In article <C0Ayt4.263@fiu.edu> feathers@serss0 (Michael Feathers) writes:
>In article <1992Dec31.050150.28929@ucc.su.OZ.AU> maxtal@extro.ucc.su.OZ.AU (John MAX Skaller) writes:
>>I would like to propose that if a class has virtual functions,
>>then any destructor generated by the compiler will be virtual
>>by default.
>>
>>(The suggestion was first read by me in a paper of Markku Sakkinen,
>>who claims it was not his idea originally either.)
>>
>>Advantages: much safer, ensures correct deletion of objects
>>by default.  Removes a source of bugs. Removes the reminder
>>that its wise to do this from the FAQ.
>
>This would be a way in which a function within the source code would be
>virtual without the keyword 'virtual' having been used on it or a function of
>the same name in an inherited class.  That would bother me as a consistency
>issue.

 Yes. But it is also a way to have a virtual function which
is NOT in the source code at all. Worse, it only applies
if the base class already has at least one virtual function.

>
>>Disadvantage: might slow down destruction a little. Can be
>>fixed by the programmer explicitly declaring a non-virtual
>>destructor.
>
>The only way to make something explicity non-virtual would be the absence
>of the 'virtual' keyword, unless we add a new keyword <shudder>.

 Yes, just define a destructor in the base class without
the keyword virtual.
>
>If the destructor is going to be made virtual by that rule, there is no
>need to declare it virtual.  But we can not make it explicitly non-virtual
>unless the virtual keyword is an option.

 Sure we can:

 class X { virtual fred(); } // has a virtual destructor
 class Y { virtual fred(); ~Y(){} }; // non-virtual destructor

The rule only applies to compiler generated destructors.

--
;----------------------------------------------------------------------
        JOHN (MAX) SKALLER,         maxtal@extro.ucc.su.oz.au
 Maxtal Pty Ltd, 6 MacKay St ASHFIELD, NSW 2131, AUSTRALIA
;--------------- SCIENTIFIC AND ENGINEERING SOFTWARE ------------------




Author: dwr@cci632.cci.com (Donald W. Rouse II)
Date: Wed, 6 Jan 1993 19:12:59 GMT
Raw View
In article <lkc2k7INNajv@exodus.Eng.Sun.COM> db@argon.Eng.Sun.COM (David Brownell) writes:
>   (2a) C++ compilers don't automagically generate ANYTHING for classes
> any more:  constructors, destructors, assignment and address-of
> operators, etc.  If such routines are used but not declared and
> defined, that is an error.
>

The problem with this is that struct == class with all members public.
This would break much C code.
Better would be for the compiler not to generate default stuff
if _any_ constructor or destructor (or op=) is declared for a class;
elsewise, generate if nec.




Author: maxtal@extro.ucc.su.OZ.AU (John MAX Skaller)
Date: Thu, 31 Dec 1992 05:01:50 GMT
Raw View
I would like to propose that if a class has virtual functions,
then any destructor generated by the compiler will be virtual
by default.

(The suggestion was first read by me in a paper of Markku Sakkinen,
who claims it was not his idea originally either.)

Advantages: much safer, ensures correct deletion of objects
by default.  Removes a source of bugs. Removes the reminder
that its wise to do this from the FAQ.

Disadvantage: might slow down destruction a little. Can be
fixed by the programmer explicitly declaring a non-virtual
destructor.

Any comments?

--
;----------------------------------------------------------------------
        JOHN (MAX) SKALLER,         maxtal@extro.ucc.su.oz.au
 Maxtal Pty Ltd, 6 MacKay St ASHFIELD, NSW 2131, AUSTRALIA
;--------------- SCIENTIFIC AND ENGINEERING SOFTWARE ------------------




Author: fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON)
Date: Sat, 2 Jan 1993 14:03:43 GMT
Raw View
maxtal@extro.ucc.su.OZ.AU (John MAX Skaller) writes:

>I would like to propose that if a class has virtual functions,
>then any destructor generated by the compiler will be virtual
>by default.
>
>Advantages: much safer, ensures correct deletion of objects
>by default.  Removes a source of bugs. Removes the reminder
>that its wise to do this from the FAQ.
>
>Disadvantage: might slow down destruction a little. Can be
>fixed by the programmer explicitly declaring a non-virtual
>destructor.

I think that this situation should cause a compiler warning, rather
than adding another arbitrary rule in the language for programmers to
remember. Bugs would still occur if a programmer accidentally forgot to
make the destructor virtual. A good compiler will generate a warning
in this situation anyway (eg. g++ does, I believe).

Mind you, I do believe that there is a place in the standard for
required warnings. Claims that these are a "quality of implementation"
issue ignore the social effect of standards. There are never *any*
genuinely 100% conformant compilers, no matter what it says on the
box you bought it in. (Read the fine print on the license inside :-( ).
The truth is that standards provide a strong incentive for compiler
vendors to ship products with certain characteristics. Provided (as
with all other aspects of a standard) that they don't require an
excessive difficulty of implementation, I don't see any good reason
not to include particular required warnings as part of a standard.

[Off the topic, another situation that should have a required warning
is the (void *) to (T *) conversion. It is definitely a hole in the
type system, but making such conversion *illegal* breaks many C programs.
It broke ALL of my C programs (well, ok, except for the hello world ones :-).
A warning would have closed the hole in the type system just as well -
after all, programmers can always achieve the same effect with a cast,
so it doesn't actually "close" the hole anyway - the error message is
just like a warning, except that you have to actually modify the
program text to get it to compile.]

--
Fergus Henderson             fjh@munta.cs.mu.OZ.AU
This .signature virus is a self-referential statement that is true - but
you will only be able to consistently believe it if you copy it to your own
.signature file!