Topic: blocking inheritance


Author: allan_w@my-dejanews.com (Allan W)
Date: Wed, 8 Jan 2003 18:55:40 +0000 (UTC)
Raw View
francis.glassborow@ntlworld.com (Francis Glassborow) wrote
> I do not agree. It is precisely the public derivation from a class with
> no virtual functions that is most suspect when done by a less than
> expert programmer. It leads to slicing, and incorrect behaviour when an
> instance is passed by (possibly const) reference to its base.

Hmmm... this type of code is most suspect when done by a less than
expert programmer. Perhaps we need a way to identify expert programmers,
so we can identify cases where this is not so suspect.

> Perhaps we need compilers to detect such 'dangerous' usage.

Agreed. But simply identifying your school and the degree awarded is
not precise enough. For one thing, even if your degree is related to
programming, that doesn't tell us which languages you studied. Sometimes
there can be two experts with the same degree, but one studied C++ while
the other studied some other language. For another thing, it's perfectly
possible to become an expert without ever attending college.

What we need, then, is a standardized test. If your score is high enough,
ISO awards you an ID card. In order to turn off certain warnings, you
would have to swipe your card through a card reader attached to the
computer that's doing the compile and/or link. A central database could
be used to identify lost or stolen ID cards.

As a side benefit, the ID card would entitle experts to join secret
"expert" clubs, where we would do secret "expert" things. If we wrote
magazine articles, we would be paid at the "authors" rate instead of
just getting acknowledgement for "reader feedback." Also, the card
would get us 10% off on pizza and beer after 7:00 PM local time at
participating restaurants; see the back of the card for exclusions
and limitations. The most famous experts (Stroustrup, Sutter,
Plaguer, and so on) could appear on TV; for the rest of us, anyone
who posts 50 or more messages here per month would get to go with as
unpaid "entorage."

Interestingly, the card would be needed every time that a given
translation unit is processed. That would mean that for every project
that ever hired a certified expert, the expert would have to be present
during every full rebuild. That's built-in job security. Also, much of
the C++ Standard Library (for instance, the STL) is normally
distributed in source form. That means that whenever a non-expert
wishes to use the library in a program, s/he will have to hire an
expert to do the compiles. I can see an entire sub-industry being
born, agencies with experts for hire, paid by the minute (including
travel time).

  [Doorbell chimes]
  [Non-Expert Programmer opens the door] Hello.
  C++ Expert here.
  Ah! May I see your ID card, please?
  I never leave home without it! [Flashes card]
  Very good. It's right through this door.
  And how will you be paying today?
  Deduct it from my retainer, please. Account D-107.
  D-107... No custom work?
  No, just the standard library. Warning levels normal for the rest.
  Very well. [Swipes card] Did you want me to wait?
  Yes please... Oops! Got a warning here, expertise level 3, sub-expert.
  How do you want to handle it. Should I help, wait, or leave?
  Last time I picked help, it cost $4000 to find out I missed a semicolen.
  Should I leave, then?
  No... I don't want to wait until tomorrow. Just let me hunt...
  [Expert waits, resists the urge to help... perhaps eats discount pizza]
  Okay, I think I found it. Let's give it another go.
  Very well. [Swipes card] Good luck to you, sir.
  Thanks. Hey! Compiled clean this time!
  Congratulations, sir. [Completes paperwork] 11 minutes... $550?
  Yes, that's what I got too. On account, please. See you again tomorrow!
  You bet. [Leaves]
  [Non-Expert Programmer begins to test his newly-compiled program]

I think this can be very lucrative... but it's also altruistic...
improving the quality of programs, and all that. :^)

---
[ 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: allan_w@my-dejanews.com (Allan W)
Date: Wed, 8 Jan 2003 20:33:41 +0000 (UTC)
Raw View
scottm@toast.net ("Scott Mayo") wrote
> I can't think of a bad warning I've ever gotten from a compiler

"I never met a warning I didn't like" -- Will Rogers

---
[ 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: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Sun, 5 Jan 2003 18:33:05 +0000 (UTC)
Raw View
In article <7dc3b1ea.0301040614.38cfa9d7@posting.google.com>, Peter
Dimov <pdimov@mmltd.net> writes
>>    In my opinion a programming language should be aimed at all skill levels.
>
>That is what I said. Good warnings are aimed at all skill levels, not
>at those programmers that you perceive as "less skilled" (but may
>actually turn out to outskill you by real world measures.)

English is really horrible for logic. He meant, I think, the union of
warning addressed to each category of programmer. You mean the
intersection of those sets of warnings.

I suspect that reality lies in between. And as we are discussing things
that are QoI it should be up to the vendor to determine what best meets
the needs of their customers. As long as warning are individually
switchable the union approach seems more appropriate than the
intersection view.


--
ACCU Spring Conference 2003 April 2-5
The Conference you cannot afford to miss
Check the details: http://www.accuconference.co.uk/
Francis Glassborow      ACCU

---
[ 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: scottm@toast.net ("Scott Mayo")
Date: Mon, 6 Jan 2003 00:39:37 +0000 (UTC)
Raw View
"Peter Dimov" <pdimov@mmltd.net> wrote in message
news:7dc3b1ea.0301040614.38cfa9d7@posting.google.com...

> Agreed. Theory aside, however, in the real world teams consist of
> several programmers with different skill levels. A warning that annoys
> a significant part of the team without contributing to code quality
> gets turned off.

But that's the decision of the team. They may know that the warning is
meaningless in their context. That some group or other may have reason
to turn off a warning doesn't mean that the warning itself is bad.

I can't think of a bad warning I've ever gotten from a compiler, and I can
think of a few that I wish more compilers provided (such as inheriting
from a class without a virtual destructor). If a warning is really
inappropriate, every compiler I know of lets you turn specific warnings
off, in a region of code or overall. Use of such pragma usually spawn
some of the most interesting and defensive comments in the code. :-)




---
[ 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: witless@attbi.com (Witless)
Date: Mon, 6 Jan 2003 04:17:02 +0000 (UTC)
Raw View
Scott Mayo wrote:

> "Peter Dimov" <pdimov@mmltd.net> wrote in message
> news:7dc3b1ea.0301040614.38cfa9d7@posting.google.com...
>
> > Agreed. Theory aside, however, in the real world teams consist of
> > several programmers with different skill levels. A warning that annoys
> > a significant part of the team without contributing to code quality
> > gets turned off.
>
> But that's the decision of the team. They may know that the warning is
> meaningless in their context. That some group or other may have reason
> to turn off a warning doesn't mean that the warning itself is bad.
>
> I can't think of a bad warning I've ever gotten from a compiler, and I can
> think of a few that I wish more compilers provided (such as inheriting
> from a class without a virtual destructor). If a warning is really
> inappropriate, every compiler I know of lets you turn specific warnings
> off, in a region of code or overall.

Unfortunately neither of those methods of warning management is portable.  And
until we define a mechanism for composing #pragma's, they never will be.  I'd
settle for  either of (i) a mechanism to force evaluation of a macro as a
preprocessor directive, or (ii) macro expansion of #pragma arguments prior to
interpretation of the #pragma directive.  On the whole I'd prefer (ii).


> Use of such pragma usually spawn

> some of the most interesting and defensive comments in the code. :-)

And some of the bluest.  A new concept in syntax highlighting.  ;-)


---
[ 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: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Mon, 6 Jan 2003 18:20:39 +0000 (UTC)
Raw View
scottm@toast.net ("Scott Mayo") writes:

|                                      Use of such pragma usually spawn
| some of the most interesting and defensive comments in the code. :-)

So, if we should have something like that,  I suggest we use the CPP
directive #dogma.  Examples of use:

   #dogma don't inherit from a class without virtual desctructor
   #dogma don't accept with public virtual functions
   #dogma don't accept implementation in header files
   #dogma don't accept badly designed code

The #dogma pre-processing directive shall not be ignored when not
understood by the implementation.

--
Gabriel Dos Reis, gdr@integrable-solutions.net

---
[ 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: Daniel.Miller@tellabs.com ("Dan'l Miller")
Date: Mon, 6 Jan 2003 18:26:50 +0000 (UTC)
Raw View
Francis Glassborow wrote:
> In article <7dc3b1ea.0301040614.38cfa9d7@posting.google.com>, Peter
> Dimov <pdimov@mmltd.net> writes
>
>>>    In my opinion a programming language should be aimed at all skill
>>> levels.
>>
>>
>> That is what I said.

   No, it is not.  See below.

>> Good warnings are aimed at all skill levels, not
>> at those programmers that you perceive as "less skilled" (but may
>> actually turn out to outskill you by real world measures.)

   Ahem.  It is not I who is applying this "less skilled" judgment on warnings
(and thus the "you"s above are inappropriately lobbed toward me).  Note that my
description of the per-team selection of which warnings to turn on is
intrinsically based on making the compiler-issued warnings enforce that team's
local design and coding conventions in the purely technological domain, not
based on pejorative "less skilled" judgments between human beings who
artificially rank themselves at the person-competing-with-person level.

> English is really horrible for logic. He meant, I think, the union of
> warning addressed to each category of programmer.

   Yes, "union" is the correct interpretation.

> You mean the
> intersection of those sets of warnings.

   Yes, "intersection" would be a misinterpretation of the intent of my words.

> I suspect that reality lies in between. And as we are discussing things
> that are QoI it should be up to the vendor to determine what best meets
> the needs of their customers.

   Here I differ somewhat.  In my opinion, too much latitude is excused as QoI.
  Ultimately, a standard (or, in a different industrial context, a
software-engineering set of requirements) is ultimately a set of *minimum
expectations* to which the implementation is demanded to conform.  Often QoI
appears to be a relaxation of minimum expectations for political expediency
among (or olive branch extended toward) vendors (instead of strongly
representing end-programmer needs).  There is nothing terribly burdensome about
standardizing warnings and standardizing that each warning must be able to be
turned off or on as local conventions dictate.

> As long as warning are individually
> switchable the union approach seems more appropriate than the
> intersection view.

   Yes, my earlier posting was based on the desired ability for each team to
individually turn on and off each warning to enforce their local design and
coding conventions.

---
[ 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: pdimov@mmltd.net (Peter Dimov)
Date: Tue, 7 Jan 2003 18:53:08 +0000 (UTC)
Raw View
Daniel.Miller@tellabs.com ("Dan'l Miller") wrote in message news:<3E19B3D2.7020806@tellabs.com>...
[...]
>    Yes, my earlier posting was based on the desired ability for each team to
> individually turn on and off each warning to enforce their local design and
> coding conventions.

I can agree with this summary of your original post.

However, this assumes a perfect world where the team controls every
bit of source code, and that rarely, if ever, happens.

When foreign source code is present, the team's ability to choose
warnings is inherently limited, and the team is often forced to choose
an "intersection set". It is not uncommon for library writers to
respond with "that warning is useless; turn it off" to "your library
produces warning X at line Y" bug reports, or to #pragma away the
warning and then forget to bring it back to life at the end of the
header file... provided that the compiler supports such a #pragma at
all.

This brings me back to my original point: good warnings have a high
hit rate, which makes them less controversional, and can be avoided in
a portable way by idiomatic language use, without constraining the
programmer's ability to express a certain concept.

---
[ 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: dave@boost-consulting.com (David Abrahams)
Date: Sat, 4 Jan 2003 00:27:45 +0000 (UTC)
Raw View
Daniel.Miller@tellabs.com ("Dan'l Miller") writes:

>    In my opinion a programming language should be aimed at all skill
> levels. The danger that Standard C++ may well be running into is
> becoming a language whose reason to exist is to address merely the
> needs of "library writers".

I agree.  It's interesting to note, however, that some of the
languages that are considered easiest to write and understand do not
capture notions such as access restrictions and const-ness.  Blocking
inheritance in such languages would be anti-idiomatic.  I'm thinking
of lightweight languages like Python, here.

>> Useful warnings have a high "hit rate" regardless of skill, and can
>> be avoided by idiomatic use of the language, without a compiler
>> switch.
>
>    The usefulness of warnings is in the eyes of each beholder.  The
> usefulness of warnings is not determined by a single individual,
> based on that single individual's non-omniscient viewpoint and
> subset-of-the-universe background. Indeed, the usefulness of

<snip more of the same>

I don't think Peter was trying to tell anyone which specific warnings
are useful, but rather trying to characterize the warnings that
everyone finds to be useful.  I think it's probably true that warnings
which often flag non-problems are more annoying than useful.

--
                       David Abrahams
   dave@boost-consulting.com * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution

---
[ 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: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Sat, 4 Jan 2003 06:26:42 +0000 (UTC)
Raw View
francis.glassborow@ntlworld.com (Francis Glassborow) writes:

[...]

| >A few more restictions, which would cause fewer false positives, come
| >    to mind:
| >
| >    (a) A class must be derived from a class with a virtual function
| >        and a non-trivial destructor, but a non-virtual destructor.
| >
| >    (b) Such a derived class must be allocated with 'new'
|
| I do not agree. It is precisely the public derivation from a class
| with no virtual functions that is most suspect when done by a less
| than expert programmer.

Do you mean that only an expert programmer should write function object
classes ?

--
Gabriel Dos Reis, gdr@integrable-solutions.net

---
[ 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: pdimov@mmltd.net (Peter Dimov)
Date: Sat, 4 Jan 2003 20:00:56 +0000 (UTC)
Raw View
francis.glassborow@ntlworld.com (Francis Glassborow) wrote in message news:<YT5HSEHXxeF+EwrV@robinton.demon.co.uk>...
> In article <7dc3b1ea.0301030541.48219b9@posting.google.com>, Peter Dimov
> <pdimov@mmltd.net> writes
> >Warnings that target "less skilled" programmers are, in my experience,
> >a waste of time and resources. Less skilled programmers, as a rule,
> >simply ignore warnings.
>
> And some wonder if C++ might be loosing popularity:-) Sorry but we
> really should address the needs of the average programmer and try and
> make it easier for them to do better.

Of course we should, but making <functional> and <map> (and many
respectable third party libraries) emit several pages of warnings
might not be the best approach. ;-)

I rather like your "explicit inheritance" suggestion, for example.

---
[ 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: pdimov@mmltd.net (Peter Dimov)
Date: Sun, 5 Jan 2003 07:43:23 +0000 (UTC)
Raw View
Daniel.Miller@tellabs.com ("Dan'l Miller") wrote in message news:<3E15C833.1010102@tellabs.com>...
> Peter Dimov wrote:
> > Warnings that target "less skilled" programmers are, in my experience,
> > a waste of time and resources. Less skilled programmers, as a rule,
> > simply ignore warnings.
>
>    In my opinion a programming language should be aimed at all skill levels.

That is what I said. Good warnings are aimed at all skill levels, not
at those programmers that you perceive as "less skilled" (but may
actually turn out to outskill you by real world measures.)

> The danger that Standard C++ may well be running into is becoming a language
> whose reason to exist is to address merely the needs of "library writers".

This is not as dangerous as it may seem. C++ is a language in which
"library writers" (quotes yours) are able to create sublanguages that
do the work (much) better than "raw C++".

[...]
> > Useful warnings have a high "hit rate" regardless of skill, and can be
> > avoided by idiomatic use of the language, without a compiler switch.
>
>    The usefulness of warnings is in the eyes of each beholder.  The usefulness
> of warnings is not determined by a single individual, based on that single
> individual's non-omniscient viewpoint and subset-of-the-universe background.
> Indeed, the usefulness of warnings for all of humankind is not determined by a
> single collection of individuals, because one size does not fit all.  Truly
> useful warnings are those chosen by each team of engineers/programmers to
> enforce self-regulations determined by that local team of engineers/programmers,
> which are typically expressed in that team's coding conventions and design
> conventions. [...]

Agreed. Theory aside, however, in the real world teams consist of
several programmers with different skill levels. A warning that annoys
a significant part of the team without contributing to code quality
gets turned off.

We can argue at length whether that particular disabled warning is
"useful" or not, but this simply doesn't matter. To "survive in the
hostile environment" and be left on, warnings need certain traits that
I have tried to enumerate above.

---
[ 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: brangdon@cix.co.uk (Dave Harris)
Date: Thu, 2 Jan 2003 21:43:24 +0000 (UTC)
Raw View
allan_w@my-dejanews.com (Allan W) wrote (abridged):
> It seems to me that Scott wasn't saying, "We should do whatever Java
> does." Instead, I think Scott was saying, "Here's a case where
> the keyword being debated was useful -- which proves that it CAN
> be useful. That doesn't  mean that this keyword is the only way to do
> it -- but it does work, so please consider that as you deliberate
> about using it yourselves."

Eiffel is another language with "final" - although there it is spelt
"frozen". Eiffel may be more relevant than Java because it is closer to
C++ (syntax apart). For example, it has stack-allocated value objects
(called "expanded" rather than "auto"), operator overloading, multiple
inheritance, genericity.

"Frozen" applies to functions, and it works as in Java. That is, functions
are virtual by default, and a derived class can make an inherited virtual
function non-virtual, which makes it non-virtual for all further derived
classes.

Eiffel has no direct way to prevent a class from having subclasses, nor to
restrict a pointer to only point to a base class.

The rationale stresses guaranteeing a particular implementation - the
same motivation offered by some of us here. It is used in several key
places in the standard library. Meyer says it should not be used for
performance (he has great faith in optimising compilers). See "Object
Oriented Software Construction" for more details. "Frozen" is in the
index.

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."

---
[ 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: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Thu, 2 Jan 2003 22:45:10 +0000 (UTC)
Raw View
francis.glassborow@ntlworld.com (Francis Glassborow) writes:

| In article <m37kdnq4kf.fsf@uniton.integrable-solutions.net>, Gabriel
| Dos Reis <gdr@integrable-solutions.net> writes
| >| Any implementation that issues warnings should provide a mechanism for
| >| switching them off. However those reading this news group should
| >| remember that the vast majority of those who program in C++ are much
| >| less skilled than they are.
| >
| >I agree.  But how does that suddenly make such a switch less noisy in
| >the context of modern C++?
|
| Then you would choose to leave such diagnostics switched off.

Yes.  That is why I said:

 # | If they do they better make sure it can be reliably disabled.
 #
 # Strongly agreed.  From my experience, I find it useless.

| >The fix to the "skillful" problem is education.
|
| Sorry but that is not realistic. Most programmers are working at least
| two levels of sophistication below you. Education will not solve the
| problem. Of course, as has happened to other languages (Forth is still
| in use by those who understand how to use a TIL and is an excellent
| language for bespoke code but most would consider it a dead language),

Forth is reincarned as PostScript ;-)

| the problem may resolve itself when all but the most expert leave for
| other pastures.
|
| We need to distinguish 'I do not need that.' from 'That is useless.'

Completely agreed:  That is why I didn't say "That is useless"; I took
caution and said "*I* find it useless".

--
Gabriel Dos Reis, gdr@integrable-solutions.net

---
[ 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: llewelly.@@xmission.dot.com (llewelly)
Date: Fri, 3 Jan 2003 05:19:45 +0000 (UTC)
Raw View
gdr@integrable-solutions.net (Gabriel Dos Reis) writes:
[snip]
> In my experience: No. With "warning for assignement in conditional
> expressions", I can compile most of the third party libraries I used
> on daily basis. That is not the case for the "warning for derivation
> from class with non-virtual ctor".  And modern C++ is such that
> idiomatic constructs make heavy uses of derivation from class with
> non-virtual destructor.  Such a warning, in the context of modern C++,
> is more noisy than useful.
>
> francis.glassborow@ntlworld.com (Francis Glassborow) writes:
> | Any implementation that issues warnings should provide a mechanism for
> | switching them off. However those reading this news group should
> | remember that the vast majority of those who program in C++ are much
> | less skilled than they are.
>
> I agree.  But how does that suddenly make such a switch less noisy in
> the context of modern C++?
[snip]

First, let us examine an existing implementation. gcc 3.2.1 and 2.95.3
    provide this feature, with the flag -Wnon-virtual-dtor
    (-Wno-non-virtual-dtor disables the warning.) The warning is given
    iff a class has virtual functions, *and* a non-trivial non-virtual
    destructor. It is worth pointing out that in the majority of the
    idioms which involve deriving from a class with a non-virtual
    dtor, the base class has no virtual functions, or has a trivial
    destructor.

A few more restictions, which would cause fewer false positives, come
    to mind:

    (a) A class must be derived from a class with a virtual function
        and a non-trivial destructor, but a non-virtual destructor.

    (b) Such a derived class must be allocated with 'new'


---
[ 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: pdimov@mmltd.net (Peter Dimov)
Date: Fri, 3 Jan 2003 16:44:00 +0000 (UTC)
Raw View
francis.glassborow@ntlworld.com (Francis Glassborow) wrote in message news:<eKYWEkHK$XD+EwLN@robinton.demon.co.uk>...
> In article <m31y44ff4p.fsf@uniton.integrable-solutions.net>, Gabriel Dos
> Reis <gdr@integrable-solutions.net> writes
> >petebecker@acm.org (Pete Becker) writes:
> >
> >> Francis Glassborow wrote:
> >| >
> >| > Considering the number of language implementors that read this
> >| > newsgroup, perhaps one or more of them would consider issuing a warning
> >| > when code derives from a class that has a non-virtual dtor.
> >| >
> >|
> >| If they do they better make sure it can be reliably disabled.
> >
> >Strongly agreed.  From my experience, I find it useless.
>
> About as useless as warnings for assignments in conditional expressions?
> Any implementation that issues warnings should provide a mechanism for
> switching them off. However those reading this news group should
> remember that the vast majority of those who program in C++ are much
> less skilled than they are.

Warnings that target "less skilled" programmers are, in my experience,
a waste of time and resources. Less skilled programmers, as a rule,
simply ignore warnings.

Useful warnings have a high "hit rate" regardless of skill, and can be
avoided by idiomatic use of the language, without a compiler switch.

A warning that is triggered by every function object in the standard
library cannot be considered to indicate non-idiomatic or badly
designed code, can 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Fri, 3 Jan 2003 18:41:13 +0000 (UTC)
Raw View
llewelly.@@xmission.dot.com (llewelly) writes:

| gdr@integrable-solutions.net (Gabriel Dos Reis) writes:
| [snip]
| > In my experience: No. With "warning for assignement in conditional
| > expressions", I can compile most of the third party libraries I used
| > on daily basis. That is not the case for the "warning for derivation
| > from class with non-virtual ctor".  And modern C++ is such that
| > idiomatic constructs make heavy uses of derivation from class with
| > non-virtual destructor.  Such a warning, in the context of modern C++,
| > is more noisy than useful.
| >
| > francis.glassborow@ntlworld.com (Francis Glassborow) writes:
| > | Any implementation that issues warnings should provide a mechanism for
| > | switching them off. However those reading this news group should
| > | remember that the vast majority of those who program in C++ are much
| > | less skilled than they are.
| >
| > I agree.  But how does that suddenly make such a switch less noisy in
| > the context of modern C++?
| [snip]
|
| First, let us examine an existing implementation. gcc 3.2.1 and 2.95.3
|     provide this feature, with the flag -Wnon-virtual-dtor
|     (-Wno-non-virtual-dtor disables the warning.) The warning is given
|     iff a class has virtual functions, *and* a non-trivial non-virtual
|     destructor.

This is not what has been mentioned.  Here is what has been mentioned:

  > Considering the number of language implementors that read this
  > newsgroup, perhaps one or more of them would consider issuing a warning
  > when code derives from a class that has a non-virtual dtor.

That is implemented in GCC as -Weffc++:

gcc/cp/class.c::check_bases():

        /* Effective C++ rule 14.  We only need to check TYPE_POLYMORPHIC_P
         here because the case of virtual functions but non-virtual
         dtor is handled in finish_struct_1.  */
      if (warn_ecpp && ! TYPE_POLYMORPHIC_P (basetype)
          && TYPE_HAS_DESTRUCTOR (basetype))
        warning ("base class `%#T' has a non-virtual destructor",
                    basetype);

Just check out this with your favorite version of g++:

   template<typename T>
     struct vector;

   template<>
     struct vector<void*> {
       vector() { /* ... */ }
       ~vector() { /* ... */ }
     };

   template<typename T>
     struct vector<T*> : private vector<void*> {
      // ...
     };

   int main()
   {
     vector<int*> v;
   }

--
Gabriel Dos Reis, gdr@integrable-solutions.net

---
[ 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: kanze@gabi-soft.de (James Kanze)
Date: Fri, 3 Jan 2003 18:43:31 +0000 (UTC)
Raw View
gdr@integrable-solutions.net (Gabriel Dos Reis) wrote in message
news:<m3el7yznen.fsf@uniton.integrable-solutions.net>...

> [...]

> | > No class derived from B could override A::do_f with the access
> | > extriction (maybe except by fraud).

> | So what you are proposing is that I reimplement virtual functions by
> | hand anytime I need to enforce class invariants.

> No.

> If that were the case, I would have told you "use the virtual keyword".

But your example basically did manually what the compiler does
automatically when the function is declared virtual.

> | Or more realistically, that I drop virtual functions systematically
> | in favor of pointers to functions (or pointers to member functions),
> | since practically speaking, the authors of the base class cannot
> | know in advance that the derived class will need to block further
> | overriding.

> So you want "final" in the language as an after-thought, a substitute
> for design and planning.  If that were to be the purpose of that
> feature, I would vote "no".  Sorry.  If you want virtual functions,
> you know what its semantics are.  See below.

One of the cases where I want to declare a function final is in a class
derived from std::streambuf, where I want to declare underflow and sync
final -- in my particular implementation, they have a necessary
relationship with one another, and overriding one without overriding the
other will cause the class to fail.  Your suggestion to solve this
requires replacing the virtual functions in streambuf with pointers to
functions.

Somehow I doubt that the people who actually implement versions of the
standard library would like this.  (Seriously, I doubt that you would
like it.)

> [...]

> | > | They're totally irrelevant in the context of which I am
> | > | speaking.

> | > No, they aren't.  Just like Mr. Jourdain was speaking prose all
> | > his life, you were using pointers to functions all the time.

> | When I want a pointer to an arbitrary function, I use pointers to
> | functions.  When I want a pointer to a member function, I use
> | pointers to member functions (and defend my use -- a lot of people
> | don't like them).  And when I want virtual functions, I use virtual
> | functions.

> Good!  So where is the problem, then?

I have a virtual function.  I've provided an implementation for it.  And
that particular implementation is important in order to maintain the
class invariants of my class (not of the base class, which originally
declared the function virtual).  I don't want a derived class to be able
to override it.

> | I don't care about the implementation details.  I'm concerned about
> | the semantics.

> Who is not?

> The point of the previous exercice is to show you how you can get your
> feature already with current C++.

By means of reimplementing the virtual function mechanism explicitly.
By means of changes in a base class which I don't necessarily control.

> You're free to transmoglify it into an agent or whatnot class if that
> appears "more readable" to you.  But the point remains that you can
> restrict run-time customization with current C++.

> | And the semantics of a virtual function are NOT the same as those of
> | a pointer to a function.

> That was precisely my point!

> The semantics of virtual functions imply: "*any* derived class _can_
> override it".  If you want to break that invariant, then you don't
> want to use virtual functions.  Period.

You don't seem to understand how inheritance (for polymorphism) works.
According to the LSP, I CAN add stricter class invariants in my derived
class.  I do so in almost every derivation of std::streambuf that I
make, for example.  These additional invariants restrict customization;
that's what they are there for.  You can derive a pipestreambuf from
streambuf, since a pipestreambuf presumably will respect all of the
streambuf invariants, and the streambuf contract.  You can't derive it
from my FilteringInputStreabufBase, because a pipestreambuf isn't a
filtering input streambuf.  As it is, FilteringInputStreabufBase is a
customization of a streambuf, but it is a customization which allows
further customization -- restricted to ways IT defines (just as classes
deriving from streambuf are restricted in the ways they can customize
it).

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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: kanze@gabi-soft.de (James Kanze)
Date: Fri, 3 Jan 2003 18:43:59 +0000 (UTC)
Raw View
hyrosen@mail.com (Hyman Rosen) wrote in message
news:<1041369930.44935@master.nyc.kbcfp.com>...
> James Kanze wrote:
> > What are the disadvantages of a function level final?

> It's just a philosophical debate. You are saying that to insure
> correctness, you wish to prevent anyone from overriding certain
> functions. I am saying that there may come a future user who needs to
> override the function and is blocked from doing something because the
> function has been made final.

> In my own experience, I have encountered functions which I wished were
> virtual but were not, because I had a specific need to modify the
> class behavior in that way, which the class designer had not
> anticipated.

In that case, you should be arguing that all functions must be virtual,
always.

My experience is that if you do extend a class in a way the class
designer had not anticipated, the results are, more often than not, a
class which doesn't work.

>  > For the data masks, we provided an abstract class DataMask, which
>  > derived from Mask.  This class defined *all* of the pure virtual
>  > functions in Mask, and declared a new set of pure virtual functions
>  > for the actual data mask to override.

> In C++, I would think this would look something like this -
>
> struct MaskInterface { /* set of pure virtuals for the windows */ };
> struct MaskImplementation : MaskInterface { /* window overrides */ };

> struct DataInterface { /* set of pure virtuals for the data people */ };
> struct DataImplementation_1 : DataInterface { /* data overrides */ };
> struct DataImplementation_2 : DataInterface { /* data overrides */ };
> ...

> template <typename DataImpl, typename MaskImpl>
> struct DataMask : DataImpl, MaskImpl { };

> This lets the data group build the DataImplementations without needing
> to know anything about Masks. Of course, Java doesn't have multiple
> inheritance (or templates!) so you can't do this in that language.  So
> perhaps this is another case where final solves a Java problem that
> C++ doesn't have.

Were it that simple.  I occasionally use mixin's like this, but in this
case, the data masks did have to know that they were masks.  For a
number of reasons.

That doesn't mean that there aren't other solutions.  There probably
are.  But they aren't nearly as accessible or as readable as blocking
overriding.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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: Daniel.Miller@tellabs.com ("Dan'l Miller")
Date: Fri, 3 Jan 2003 18:47:01 +0000 (UTC)
Raw View
Peter Dimov wrote:
> francis.glassborow@ntlworld.com (Francis Glassborow) wrote in message news:<eKYWEkHK$XD+EwLN@robinton.demon.co.uk>...
>
>>In article <m31y44ff4p.fsf@uniton.integrable-solutions.net>, Gabriel Dos
>>Reis <gdr@integrable-solutions.net> writes
>>
>>>petebecker@acm.org (Pete Becker) writes:
>>>
>>>
>>>>Francis Glassborow wrote:
>>>
>>>| >
>>>| > Considering the number of language implementors that read this
>>>| > newsgroup, perhaps one or more of them would consider issuing a warning
>>>| > when code derives from a class that has a non-virtual dtor.
>>>| >
>>>|
>>>| If they do they better make sure it can be reliably disabled.
>>>
>>>Strongly agreed.  From my experience, I find it useless.
>>
>>About as useless as warnings for assignments in conditional expressions?
>>Any implementation that issues warnings should provide a mechanism for
>>switching them off. However those reading this news group should
>>remember that the vast majority of those who program in C++ are much
>>less skilled than they are.
>
>
> Warnings that target "less skilled" programmers are, in my experience,
> a waste of time and resources. Less skilled programmers, as a rule,
> simply ignore warnings.

   In my opinion a programming language should be aimed at all skill levels.
The danger that Standard C++ may well be running into is becoming a language
whose reason to exist is to address merely the needs of "library writers".

   There are different very valid needs needed by less-skilled programmers,
real-time embedded engineers, OO "business object" designers, and
injected-programming-paradigm "library writers".  Furthermore these needs vary
from one body of source code developed by some team of people to the next body
of source code developed by a different team of people.

> Useful warnings have a high "hit rate" regardless of skill, and can be
> avoided by idiomatic use of the language, without a compiler switch.

   The usefulness of warnings is in the eyes of each beholder.  The usefulness
of warnings is not determined by a single individual, based on that single
individual's non-omniscient viewpoint and subset-of-the-universe background.
Indeed, the usefulness of warnings for all of humankind is not determined by a
single collection of individuals, because one size does not fit all.  Truly
useful warnings are those chosen by each team of engineers/programmers to
enforce self-regulations determined by that local team of engineers/programmers,
which are typically expressed in that team's coding conventions and design
conventions.  Useful warnings cannot be chosen universally for people throughout
the world as a one-size-fits-all edict from some central supposed-authority.
Indeed useful warnings cannot be chosen universally for every line of every file
of a single local body of source code.  Rather, for warnings to be useful, the
warnings must be intimately tied into that local team's self-determined coding
conventions and design conventions.

> A warning that is triggered by every function object in the standard
> library cannot be considered to indicate non-idiomatic or badly
> designed code, can it?

   Such a warning can indicate code which is outside of the norm if the standard
library deviates from the expectations of the customer engineers/programmers
worldwide who do not sit on standards committees or if the implementation of
that standard library blithely does not comply with the established
shared-wisdoms of the larger community.  (It is thoroughly embarrassing that
there is at least one huge compiler vendor's standard library on a
widely-deployed operating system which hemorrhages warnings when the warning
level is turned all of the way up when compiling mere *usage* of that vendor's
standard libraries in a body of source code.)

   Remember, standards are not good because they emanate authoritatively from an
all-powerful central government which dictates what that government views as
good medicine.  Rather, standards are good because they embody the agreed-upon
*shared wisdoms* of knowledgeable experts in the field, both those governing
experts serving in the representative government of a standards body as well as
those governed experts in the governed populace outside of a standards body.  If
a standards body moves too far away too aggressively from the populace that they
govern, then the populace can relatively easily emigrate to a different
territory governed by a more hospitable/agreeable government.

---
[ 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: nikb@webmaster.com ("Nikolaos D. Bougalis")
Date: Fri, 3 Jan 2003 18:47:12 +0000 (UTC)
Raw View
"Pete Becker" <petebecker@acm.org> wrote in message
news:3DF535C2.EEB15366@acm.org...
> "James Kuyper Jr." wrote:
> >
> > Pete Becker wrote:
> > ....
> > > If youblet users arbitrarily change the contents of your class then
the
> > > code you wrote to implement your class won't work right.
> >
> > The same is true, in some circumstances, if you let users arbitrarily
> > derive from your class.
> >
>
> Nice claim. Do you have code to demonstrate it?


class base
{
public:
 /* constructors, etc ommited */

 void *operator new(size_t sz)
 {
  // this class uses a slab allocator. the slabber cannot give
  // pointers to memory blocks whose size is != sizeof(base)
  return get_slab_memory();
 }

 /* operator delete ommited */
};


class derived : public base
{
 /* details ommited */
};

int main(int argc, char **argv)
{
 derived *d = new derived;

 /* congratulations! the memory returned by base::operator new
  * is not big enough to accomodate a derived...
  */
}

    Arguably, you could put an assert() in base::operator new, which would
catch the size mismatch (assert(sz == sizeof(base)) at *run time* but being
able to limit derivation from the base class in this instance could be a
good idea. Before you write the above example as unrealistic, I have seen
many classes (e.g. a hash entry objects, or a list entry objects) that use
slab allocators in that fashion. Furthermore, those kinds objects were never
meant to be base classes for anything.

    Also, note that the lack of a virtual destructor in the base class -- a
conscious decision, since base was never meant to be derived from  -- could
cause memory leaks if derived objects are deleted by pointers to the base
class.

    -n

---
[ 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: llewelly.@@xmission.dot.com (llewelly)
Date: Fri, 3 Jan 2003 19:39:27 +0000 (UTC)
Raw View
gdr@integrable-solutions.net (Gabriel Dos Reis) writes:

[snip]
> | First, let us examine an existing implementation. gcc 3.2.1 and 2.95.3
> |     provide this feature, with the flag -Wnon-virtual-dtor
> |     (-Wno-non-virtual-dtor disables the warning.) The warning is given
> |     iff a class has virtual functions, *and* a non-trivial non-virtual
> |     destructor.
>
> This is not what has been mentioned.  Here is what has been mentioned:
>
>   > Considering the number of language implementors that read this
>   > newsgroup, perhaps one or more of them would consider issuing a warning
>   > when code derives from a class that has a non-virtual dtor.

>
> That is implemented in GCC as -Weffc++:

I'm sorry - It never occured to me there might be two variants of the
    same warning. Especially since one of them is useful, but the
    other is not.

[example snipped, but thank you for 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Fri, 3 Jan 2003 20:26:53 +0000 (UTC)
Raw View
kanze@gabi-soft.de (James Kanze) writes:

| gdr@integrable-solutions.net (Gabriel Dos Reis) wrote in message
| news:<m3el7yznen.fsf@uniton.integrable-solutions.net>...
|
| > [...]
|
| > | > No class derived from B could override A::do_f with the access
| > | > extriction (maybe except by fraud).
|
| > | So what you are proposing is that I reimplement virtual functions by
| > | hand anytime I need to enforce class invariants.
|
| > No.
|
| > If that were the case, I would have told you "use the virtual keyword".
|
| But your example basically did manually what the compiler does
| automatically when the function is declared virtual.

Oh, really?  Somewhere in this thread you asserted that pointer to
functions has nothing to do with the issue at hand.  Now you're
stating that what I showed basically do what the compiler does for
virtual funtions.  I think that somewhere there is a consistency
problem with the assertions you made.

[...]

| > | > | They're totally irrelevant in the context of which I am
| > | > | speaking.
|
| > | > No, they aren't.  Just like Mr. Jourdain was speaking prose all
| > | > his life, you were using pointers to functions all the time.
|
| > | When I want a pointer to an arbitrary function, I use pointers to
| > | functions.  When I want a pointer to a member function, I use
| > | pointers to member functions (and defend my use -- a lot of people
| > | don't like them).  And when I want virtual functions, I use virtual
| > | functions.
|
| > Good!  So where is the problem, then?
|
| I have a virtual function.  I've provided an implementation for it.  And
| that particular implementation is important in order to maintain the
| class invariants of my class (not of the base class, which originally
| declared the function virtual).  I don't want a derived class to be able
| to override it.

But you also know that what semantics of a virtual function are.  If
you do not want it to be overridden, you should not use a virtual
function in the first place.

| > | I don't care about the implementation details.  I'm concerned about
| > | the semantics.
|
| > Who is not?
|
| > The point of the previous exercice is to show you how you can get your
| > feature already with current C++.
|
| By means of reimplementing the virtual function mechanism explicitly.

The above has a consistency problem with your previous assertion about
pointer to functions having nothing to do with the issue at hand.

[...]

| You don't seem to understand how inheritance (for polymorphism) works.

Thank you, I do fully understand how run-time polymorphism (either
through inheritance or without it) works.  Not just because I happen
to disagree with you on a particular topic means I do not understand
how inheritance for polymorphism works.  Actually, it /might/ be you
that do not understand polymorphism.  However, I -- contrary to your
previous posting -- will not be so condescendent and will make a more
workable assumption: You understand how inheritance works but we
happen to disagree oon what we should put in the language.
Disagreement about technical issues does not always imply ignorance.


| According to the LSP, I CAN add stricter class invariants in my derived
| class.

Sure you can do whatever pleases you but blocking overriding is -not-
part of the semantics of virtual function.

Virtual function is *a* way to implement run-time polymorphism, but
it is not the single way to achieve it.  There are alternatives and
C++ do provide such alternatives.  It was shown in this thread how you
could add the invariant "that this behaviour is not overridable".

--
Gabriel Dos Reis, gdr@integrable-solutions.net

---
[ 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: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Fri, 3 Jan 2003 20:27:47 +0000 (UTC)
Raw View
Daniel.Miller@tellabs.com ("Dan'l Miller") writes:

| Furthermore these needs vary from one body of source code developed by
| some team of people to the next body of source code developed by a
| different team of people.

Agreed.  But I'm of the opinion that the language should aim at
providing features that are consistent with the various paradigms it
supports.

| > Useful warnings have a high "hit rate" regardless of skill, and can be
| > avoided by idiomatic use of the language, without a compiler switch.
|
|    The usefulness of warnings is in the eyes of each beholder.

Agreed, that is why I was careful and made a personal statement -- did
you have a chance to read it?

[...]

|                                    Indeed, the usefulness of warnings
| for all of humankind is not determined by a single collection of
| individuals, because one size does not fit all.

But the development of the C++ language is the work of a community
which is a collection of individuals.   Same for C++ implementations.

[...]

|                                               Rather, standards are
| good because they embody the agreed-upon *shared wisdoms* of

And the problem here is a disagreement about a particular view on
inheirtance.

--
Gabriel Dos Reis, gdr@integrable-solutions.net

---
[ 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: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Fri, 3 Jan 2003 20:28:12 +0000 (UTC)
Raw View
In article <7dc3b1ea.0301030541.48219b9@posting.google.com>, Peter Dimov
<pdimov@mmltd.net> writes
>Warnings that target "less skilled" programmers are, in my experience,
>a waste of time and resources. Less skilled programmers, as a rule,
>simply ignore warnings.

And some wonder if C++ might be loosing popularity:-) Sorry but we
really should address the needs of the average programmer and try and
make it easier for them to do better. If we want to be elitist, fine but
the drift away from C++ in the lecture room and classroom will continue
to accelerate.


--
ACCU Spring Conference 2003 April 2-5
The Conference you cannot afford to miss
Check the details: http://www.accuconference.co.uk/
Francis Glassborow      ACCU

---
[ 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: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Fri, 3 Jan 2003 21:26:24 +0000 (UTC)
Raw View
francis.glassborow@ntlworld.com (Francis Glassborow) writes:

| In article <7dc3b1ea.0301030541.48219b9@posting.google.com>, Peter
| Dimov <pdimov@mmltd.net> writes
| >Warnings that target "less skilled" programmers are, in my experience,
| >a waste of time and resources. Less skilled programmers, as a rule,
| >simply ignore warnings.
|
| And some wonder if C++ might be loosing popularity:-) Sorry but we
| really should address the needs of the average programmer and try and
| make it easier for them to do better.

Completely agreed.  But features that are not consistent with the
language and the paradigms it supports won't help them either.

| If we want to be elitist, fine but the drift away from C++ in the
| lecture room and classroom will continue to accelerate.

I do not believe the issue is really about being elitist or not.

--
Gabriel Dos Reis, gdr@integrable-solutions.net

---
[ 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: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Sat, 4 Jan 2003 00:24:25 +0000 (UTC)
Raw View
In article <86bs2ysvu7.fsf@Zorthluthik.foo>, llewelly
<"llewelly."@?.dot.com.invalid> writes
>First, let us examine an existing implementation. gcc 3.2.1 and 2.95.3
>    provide this feature, with the flag -Wnon-virtual-dtor
>    (-Wno-non-virtual-dtor disables the warning.) The warning is given
>    iff a class has virtual functions, *and* a non-trivial non-virtual
>    destructor. It is worth pointing out that in the majority of the
>    idioms which involve deriving from a class with a non-virtual
>    dtor, the base class has no virtual functions, or has a trivial
>    destructor.
>
>A few more restictions, which would cause fewer false positives, come
>    to mind:
>
>    (a) A class must be derived from a class with a virtual function
>        and a non-trivial destructor, but a non-virtual destructor.
>
>    (b) Such a derived class must be allocated with 'new'

I do not agree. It is precisely the public derivation from a class with
no virtual functions that is most suspect when done by a less than
expert programmer. It leads to slicing, and incorrect behaviour when an
instance is passed by (possibly const) reference to its base.

Perhaps we need compilers to detect such 'dangerous' usage.


--
ACCU Spring Conference 2003 April 2-5
The Conference you cannot afford to miss
Check the details: http://www.accuconference.co.uk/
Francis Glassborow      ACCU

---
[ 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: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Sat, 4 Jan 2003 00:25:38 +0000 (UTC)
Raw View
pdimov@mmltd.net (Peter Dimov) writes:

| A warning that is triggered by every function object in the standard
| library cannot be considered to indicate non-idiomatic or badly
| designed code, can it?

I happen to understand that respectable people posting to csc++ or
clmc++ considere the Standard Library as badly designed :-) :-)

--
Gabriel Dos Reis, gdr@integrable-solutions.net

---
[ 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: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Thu, 2 Jan 2003 14:23:12 +0000 (UTC)
Raw View
scottm@toast.net ("Scott Mayo") writes:

| Sometimes classes are meant to be internal to a design,
| and attempts to mess with them, extend them or twerk
| their internals, end in tears, or at least in support calls that I
| have to answer. And completely hiding such classes from
| external eyes can be a struggle.

Well, C++ has the notion of incomplete type.  The use of that concept
in practice means that the in header files, the class is just forward
declared; its implementation is put in an implementatiion file (a .C
or .cc or .wathever) file.  That works in practice.
What is the struggle you're talking about?

--
Gabriel Dos Reis, gdr@integrable-solutions.net

---
[ 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: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Thu, 2 Jan 2003 18:31:59 +0000 (UTC)
Raw View
francis.glassborow@ntlworld.com (Francis Glassborow) writes:

| In article <m31y44ff4p.fsf@uniton.integrable-solutions.net>, Gabriel
| Dos Reis <gdr@integrable-solutions.net> writes
| >petebecker@acm.org (Pete Becker) writes:
| >
| >> Francis Glassborow wrote:
| >| >
| >| > Considering the number of language implementors that read this
| >| > newsgroup, perhaps one or more of them would consider issuing a warning
| >| > when code derives from a class that has a non-virtual dtor.
| >| >
| >|
| >| If they do they better make sure it can be reliably disabled.
| >
| >Strongly agreed.  From my experience, I find it useless.
|
| About as useless as warnings for assignments in conditional expressions?

In my experience: No. With "warning for assignement in conditional
expressions", I can compile most of the third party libraries I used
on daily basis. That is not the case for the "warning for derivation
from class with non-virtual ctor".  And modern C++ is such that
idiomatic constructs make heavy uses of derivation from class with
non-virtual destructor.  Such a warning, in the context of modern C++,
is more noisy than useful.

| Any implementation that issues warnings should provide a mechanism for
| switching them off. However those reading this news group should
| remember that the vast majority of those who program in C++ are much
| less skilled than they are.

I agree.  But how does that suddenly make such a switch less noisy in
the context of modern C++?

The fix to the "skillful" problem is education.

--
Gabriel Dos Reis, gdr@integrable-solutions.net

---
[ 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: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Thu, 2 Jan 2003 19:14:28 +0000 (UTC)
Raw View
rmaddox@isicns.com (Randy Maddox) writes:

| gdr@integrable-solutions.net (Gabriel Dos Reis) wrote in message news:<m31y44irpe.fsf@uniton.integrable-solutions.net>...
| > rmaddox@isicns.com (Randy Maddox) writes:
| >
| > | hyrosen@mail.com (Hyman Rosen) wrote in message news:<1040658851.882926@master.nyc.kbcfp.com>...
| > | > James Kanze wrote:
| > | > > It's always possible to do anything.  One of the basic premises of
| > | > > programming by contract is that a class is responsible for its
| > | > > contract.
| > | >
| > | > Yes, exactly. Your class is responsible for its contract.
| > | > My derived class is responsible for its contract. Your
| > | > class is not responsible for the contract of my derived
| > | > class. You seem to assume that no one beside yourself can
| > | > maintain a contract, and therefore you won't let anyone
| > | > derive from your class.
| > | >
| > |
| > | I believe that you misstate the assumption here.  It is not that the
| > | class designer assumes that no one else can maintain a contract, but
| > | rather that the class designer knows best whether he/she has made
| > | implementation assumptions that would cause problems if the class were
| > | derived from.
| >
| > Do we have concrete examples for that scenario?
|
| The simplest would be a concrete class such as Complex or Point where
| size and efficiency are perfectly valid concerns and a virtual dtor
| would not be acceptable.

But, it is quite possible to have a class derived from Complex or
Point and have them used in conformance with those interfaces.

| Another example might be an internal pointer
| that is used in a way that further inheritance might break, e.g.,
| dereferenced and passed by value, which could result in object
| slicing.

Again, if the slicing is -not- a problem for the particular
derivation, then where is the problem?

[...]

| > | The counter argument that final is "dictatorial", "arrogant" or
| > | "paternalistic" seems a bit weak to me.
| >
| > Oh, really?
|
| Yes, really.

"dictatorial", "arrogant" or "paternatilistic" for a programming
language aren't technical arguments.

--
Gabriel Dos Reis, gdr@integrable-solutions.net

---
[ 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: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Thu, 2 Jan 2003 19:14:56 +0000 (UTC)
Raw View
kanze@gabi-soft.de (James Kanze) writes:

| Nobody is denying that inheritance has a number of uses.  Realistically,
| however, polymorphism is the most frequent,

Up to this point.  Because dynamic polymorphism was the first one put
in the language. About twenty years ago.  Advaned support for other
forms of polymorphism is quite recent in the language.  And given the
development and attention templates have received these last years and
the paradigmal shifts, increasing use of inheritance that does not fit
a particular view of polymorphism should be expected.

| I find it incredible the amount of noise my parenthetical remark has
| created.

If it were really parenthetical then it wouldn't have received that
amount of noise you're hearing.  Or maybe you're just hearing an echo? ;-)

--
Gabriel Dos Reis, gdr@integrable-solutions.net

---
[ 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: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Thu, 2 Jan 2003 19:16:37 +0000 (UTC)
Raw View
In article <m37kdnq4kf.fsf@uniton.integrable-solutions.net>, Gabriel Dos
Reis <gdr@integrable-solutions.net> writes
>| Any implementation that issues warnings should provide a mechanism for
>| switching them off. However those reading this news group should
>| remember that the vast majority of those who program in C++ are much
>| less skilled than they are.
>
>I agree.  But how does that suddenly make such a switch less noisy in
>the context of modern C++?

Then you would choose to leave such diagnostics switched off.
>
>The fix to the "skillful" problem is education.

Sorry but that is not realistic. Most programmers are working at least
two levels of sophistication below you. Education will not solve the
problem. Of course, as has happened to other languages (Forth is still
in use by those who understand how to use a TIL and is an excellent
language for bespoke code but most would consider it a dead language),
the problem may resolve itself when all but the most expert leave for
other pastures.

We need to distinguish 'I do not need that.' from 'That is useless.' I
am all in favour of education but I am also pragmatic and know that
there will never be enough.

--
ACCU Spring Conference 2003 April 2-5
The Conference you cannot afford to miss
Check the details: http://www.accuconference.co.uk/
Francis Glassborow      ACCU

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Thu, 2 Jan 2003 19:20:31 +0000 (UTC)
Raw View
Randy Maddox wrote:
>
> petebecker@acm.org (Pete Becker) wrote in message news:<3E0B435D.A0A7EF39@acm.org>...
> > Randy Maddox wrote:
> > >
> > > I believe that you misstate the assumption here.  It is not that the
> > > class designer assumes that no one else can maintain a contract, but
> > > rather that the class designer knows best whether he/she has made
> > > implementation assumptions that would cause problems if the class were
> > > derived from.
> > >
> >
> > In other words, the reason to block inheritance is to cover up
> > implementation errors. Otherwise the contract would be sufficient.
> >
> IMHO it is hard to see how taking advantage of explicit design
> assumptions to produce an implementation could be considered an error.

If they're explicit then the user knows as well as the class designer
whether he/she has made implementation assumptions that would cause
problems if the class were derived from. I.e. they're part of the
class's contract.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Tue, 31 Dec 2002 16:48:19 +0000 (UTC)
Raw View
kanze@gabi-soft.de (James Kanze) writes:

| gdr@integrable-solutions.net (Gabriel Dos Reis) wrote in message
| news:<m3wulxjcee.fsf@uniton.integrable-solutions.net>...
| > kanze@gabi-soft.de (James Kanze) writes:
|
| > [...]
|
| > | > The former is of no immediat interest to me.  So I'll concentrate
| > | > on the latter.
|
| > | > In C++ there are at least two ways to cutomize at run-time an
| > | > object behaviour:
| > | >    (1) pointer to function
| > | >    (2) virtual member function
|
| > | > With (1), on has almost total control on what is going on.
| > | > Semantics of (2) means, among other things: virtual once, virtual
| > | > forever.
|
| > | I'm not quite sure I understand you.  What do pointers to functions
| > | have to do with anything?
|
| > Because virtual functions, implementing dynamic binding, are
| > essentially pointers to functions.
|
| That's how they are implemented.  That's not how they appear to the
| programmer.

It may be that that isn't the way it doesn't appear to *you* (I don't
know whether I should say you're lucky ;-); that doesn't mean that
isn't the way it evolves from a programming point of view.  Indeed,
just ask Bjarne Stroustrup what were the reactions when he first
explained C++ virtual functions to his friends and colleagues.  Or, if
you don't want to ask him (for whatever reason), just check out D&E
for the reactions he got about C++ virtual function; you might be
surprised. Or, maybe would you say  that his friends or colleagues
weren't programmers.

Anyway, I think it is wrong not to consider the implementation side
of the issue; that adds light to the matter.  Actually, I offered
discussing both implementation and conceptual points of view, you
dismiss both points of view.

[...]

| I'm interested
| in producing large quantities of robust code, as cheaply as possible.
| I've found by hard experience that programming by contract, with actual
| enforcement, is an effective means to this end.

You may also find that considering the feature, its implementation and
its interaction from an abstract point of view is also as actual and
concrete as what you got the hard way.  You should not take "abstract"
in the previous sentence as implying something with no actual
connection with the reality of gettiing a job done.

[...]

| > No class derived from B could override A::do_f with the access
| > extriction (maybe except by fraud).
|
| So what you are proposing is that I reimplement virtual functions by
| hand anytime  I need to enforce class invariants.

No.

If that were the case, I would have told you "use the virtual keyword".

| Or more realistically,
| that I drop virtual functions systematically in favor of pointers to
| functions (or pointers to member functions), since practically speaking,
| the authors of the base class cannot know in advance that the derived
| class will need to block further overriding.

So you want "final" in the language as an after-thought, a substitute
for design and planning.  If that were to be the purpose of that
feature, I would vote "no".  Sorry.
If you want virtual functions, you know what its semantics are.  See
below.

[...]

| > | They're totally irrelevant in the context of which I am speaking.
|
| > No, they aren't.  Just like Mr. Jourdain was speaking prose all his
| > life, you were using pointers to functions all the time.
|
| When I want a pointer to an arbitrary function, I use pointers to
| functions.  When I want a pointer to a member function, I use pointers
| to member functions (and defend my use -- a lot of people don't like
| them).  And when I want virtual functions, I use virtual functions.

Good!  So where is the problem, then?

| I don't care about the implementation details.  I'm concerned about the
| semantics.

Who is not?

The point of the previous exercice is to show you how you can get your
feature already with current C++.  You're free to transmoglify it into
an agent or whatnot class if that appears "more readable" to you.  But
the point remains that you can restrict run-time customization with
current C++.

| And the semantics of a virtual function are NOT the same as
| those of a pointer to a function.

That was precisely my point!

The semantics of virtual functions imply: "*any* derived class _can_
override it".  If you want to break that invariant, then you don't
want to use virtual functions.  Period.

[...]

| > As showed above, no need for intermdiate class.
|
| If you're willing to forego readability.

Readbility is in the eyes of the beholder.

--
Gabriel Dos Reis, gdr@integrable-solutions.net

---
[ 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: kanze@gabi-soft.de (James Kanze)
Date: Tue, 31 Dec 2002 16:49:30 +0000 (UTC)
Raw View
hyrosen@mail.com (Hyman Rosen) wrote in message
news:<1040927057.651525@master.nyc.kbcfp.com>...
> James Kanze wrote:
> > I've mentionned the problem of maintaining class invariants more
> > than once.  It's a real problem, which final helped solve a couple
> > of times in Java.

> What was the nature of the problem? Did you have co-workers who
> derived from your classes and broke them?

Obviously not, since the critical functions were final:-).  In practice,
I imagine that they would have.  Not regularly, but such things do
happen from time to time in large projects -- people read the
documentation, but they forget a detail.

The problems involved varied.  In all cases, the scenario was an
interface (abstract base class -- in the general sense, and not
necessarily the Java keyword), in which one of the derived classes used
the template pattern, assuring a certain number of additional clauses in
the contract, and declared new pure virtual functions which a further
derived class overrode.  The final derived class must override the
pure virtual functions defined in our class, but should not override the
functions of the original interface, which we had already overridden.

A typical example would be the hierarchy of "masks" -- panes which were
displayed in the application area of the window.  All masks derived from
a common interface, Mask, which specified the interface used by the rest
of the framework.  Most of the masks displayed data which had to be
gotten from the host -- this introduced threading, since you can't block
waiting for the data in the GUI event handing thread.  (This is, of
course, linked to the Swing threading model, but on the whole, the Swing
threading model is one thing that the Java people got right.)

The actual masks were to be programmed by application domain specialists
(since they dealt with domain specific data).  Our job was to provide a
framework to make this as simple as possible for them; in particular, I
wouldn't have trusted any of them to handle threading issues correctly.
(This isn't a criticism of them; I wouldn't do any better with any of
the bank specific issues.  One person can't be an expert in everything.)
For the data masks, we provided an abstract class DataMask, which
derived from Mask.  This class defined *all* of the pure virtual
functions in Mask, and declared a new set of pure virtual functions for
the actual data mask to override.

In this case, the critical issue was thread safety; the "class
invariants" involved weren't so much class invariants, but rather that
the abstract implementation ensured correct synchronization with the
rest of the system, and above all, that its pure virtual functions were
called at the right time, in the right thread -- the concrete class at
the end of the chain didn't have to worry about threading at all.  The
protocol used to ensure thread safety wasn't rocket science, but it
wasn't entirely trivial either, and having one of the most derived
classes override one of the functions in the basic interface (Mask)
would have made it impossible for the abstract implementation (DataMask)
to ensure thread safety.  (For various reasons, we didn't go this route
for the printing functions.  Something we regretted deeply later: we had
no end of threading problems with them, but not one single problem with
the data acquision and synchronization using our DataMask.)

Obviously, the most important measure we took was documenting, in
DataMask, that the functions in question shouldn't be overridden.  It
would also have been possible to use delegation, rather than the
template pattern, but at the price of considerable added complexity (in
this case).  And of course, you'll never be able to prevent all abuses.
But on the whole, the use of final on these functions helped.  It's
absence certainly isn't a killer; I've gotten by without it in C++ until
now.  But it helps, and to date, no one has posted any serious negative
arguments against THIS use of final.

For a more C++ example, you might want to look at my filtering streambuf
implementation (at least, if you could -- for some reason, it's taking
an incredibly long time for me to get reconnected since my move).  In
this case, the hierarchy is:

              std::streambuf
                     |
                     |
        FilteringInputStreambufBase
                     |
                     |
    FilteringInputStreambuf< Extractor >

In this case, FilteringInputStreambufBase takes care of the buffering
and error handling; in particular, the semantics of sync and underflow
are linked.  If a derived class just overrides one, I'm in trouble, and
if it overrides both, there's really no point in its deriving from
FilteringInputStreambufBase, because none of the behavior of this class
is used.  If it were available, I would use final on these two
functions.  In this case, too, rewriting the class to use delegation
would only add a moderate amount of complexity -- much less than in the
case of Mask/DataMask above.  But why should I have to add any
complexity?  And why should I have to forego a compile time check (even
if the error hasn't proved to be excessively frequent)?  What are the
disadvantages of a function level final?

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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: Tue, 31 Dec 2002 21:31:37 +0000 (UTC)
Raw View
James Kanze wrote:
> What are the disadvantages of a function level final?

It's just a philosophical debate. You are saying that to
insure correctness, you wish to prevent anyone from overriding
certain functions. I am saying that there may come a future user
who needs to override the function and is blocked from doing
something because the function has been made final.

In my own experience, I have encountered functions which I
wished were virtual but were not, because I had a specific
need to modify the class behavior in that way, which the
class designer had not anticipated.

 > For the data masks, we provided an abstract class DataMask, which
 > derived from Mask.  This class defined *all* of the pure virtual
 > functions in Mask, and declared a new set of pure virtual functions for
 > the actual data mask to override.

In C++, I would think this would look something like this -

struct MaskInterface { /* set of pure virtuals for the windows */ };
struct MaskImplementation : MaskInterface { /* window overrides */ };

struct DataInterface { /* set of pure virtuals for the data people */ };
struct DataImplementation_1 : DataInterface { /* data overrides */ };
struct DataImplementation_2 : DataInterface { /* data overrides */ };
...

template <typename DataImpl, typename MaskImpl>
struct DataMask : DataImpl, MaskImpl { };

This lets the data group build the DataImplementations without
needing to know anything about Masks. Of course, Java doesn't
have multiple inheritance (or templates!) so you can't do this
in that language. So perhaps this is another case where final
solves a Java problem that C++ doesn't have.

---
[ 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: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Thu, 2 Jan 2003 04:09:10 +0000 (UTC)
Raw View
francis.glassborow@ntlworld.com (Francis Glassborow) writes:

| In article <d6651fb6.0212230826.58b65697@posting.google.com>, James
| Kanze <kanze@gabi-soft.de> writes
| >In general, a non-virtual public destructor is a very good sign that the
| >class was not designed with inheritance in mind, and is probably not a
| >very good candidate for derivation.  Except for special cases: should
| >std::iterator have a virtual destructor?  (Actually, an empty, inline
| >protected destructor probably wouldn't hurt it.)
|
| Considering the number of language implementors that read this
| newsgroup, perhaps one or more of them would consider issuing a
| warning when code derives from a class that has a non-virtual dtor.

Well, something similar has been implemented in GCC (for years) under
the name of -Weffc++.

Personnally, I don't find it really helpful: It can't be used to
compile the standard library.  And other libraries components just
break with it.  Said differently, I find it really useless.  But that
may be just me.

--
Gabriel Dos Reis, gdr@integrable-solutions.net

---
[ 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: dave@boost-consulting.com (David Abrahams)
Date: Sun, 29 Dec 2002 23:20:09 +0000 (UTC)
Raw View
gdr@integrable-solutions.net (Gabriel Dos Reis) writes:

> allan_w@my-dejanews.com (Allan W) writes:
>
> | kanze@gabi-soft.de (James Kanze) wrote
> | > In general, a non-virtual public destructor is a very good sign that the
> | > class was not designed with inheritance in mind, and is probably not a
> | > very good candidate for derivation.
> |
> | I'd say that a non-virtual public destructor is a very good sign
> | that the class was not designed for polymorphism. Polymorphism
> | is not the only use for derivation.
>
> This is a far better formulation of the issue.  I'm always amazed to
> see how many people (wrongly) equate inheritance with runtime
> polymorphism. Still, when I consult standard texts (like Stroustrup's
> or Koenig's) it is made pretty clear there that there can be
> inheritance *without* run-time polymorphism.

And there can also be run-time polymorphism without dynamic
allocation.  I see no reason for a virtual destructor if, for example,
operator new is private.

--
                       David Abrahams
   dave@boost-consulting.com * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution

---
[ 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: kanze@gabi-soft.de (James Kanze)
Date: Mon, 30 Dec 2002 16:16:07 +0000 (UTC)
Raw View
gdr@integrable-solutions.net (Gabriel Dos Reis) wrote in message
news:<m3wulxjcee.fsf@uniton.integrable-solutions.net>...
> kanze@gabi-soft.de (James Kanze) writes:

> [...]

> | > The former is of no immediat interest to me.  So I'll concentrate
> | > on the latter.

> | > In C++ there are at least two ways to cutomize at run-time an
> | > object behaviour:
> | >    (1) pointer to function
> | >    (2) virtual member function

> | > With (1), on has almost total control on what is going on.
> | > Semantics of (2) means, among other things: virtual once, virtual
> | > forever.

> | I'm not quite sure I understand you.  What do pointers to functions
> | have to do with anything?

> Because virtual functions, implementing dynamic binding, are
> essentially pointers to functions.

That's how they are implemented.  That's not how they appear to the
programmer.

> And those are in essence what you do.  Therefore, before going on
> requesting a keyword to revert from (2) to (1) in the middle of
> implementation, it seems appropriate to reconsider the issue in its
> original or abstract setting.

I have absolutely no interest in any abstract setting.  I'm interested
in producing large quantities of robust code, as cheaply as possible.
I've found by hard experience that programming by contract, with actual
enforcement, is an effective means to this end.  I've found by actual
experience in Java that preventing further overriding of previously
virtual functions is an effective way to enforce class invariants in
certain specific cases.

> With virtual functions, the compiler automatically sets the pointers
> with the appropriate addresses, in the appropriate classes.  And that,
> each time the compilers sees an overriding function.

> What you seems to want is to have a way to tell the compiler to accept
> no more overrider, starting from a point in the class hierarchy.

That's exactly what I want.

> Now, let's see how you can achieve the same effect in current C++.
> The ingredients are:
>   (1) pointer to function; and
>   (2) accessiibility.

> With pointer to function, you implement dynamic binding and with
> control access you restrict/forbid access for derrived classes,
> therefore prevents any further run-time customization.

> Suppose we have a class A that wants to implement a function that may
> be "finalized" latter in the class hierarchy.  You're known to use
> design-by-contract in the sense that you make your virtual function
> protected and have the public function non-virtual that calls it.

>    struct A {

>       void f(int i)    // calls do_f
>       {
>         pre_condition(i);
>         do_f(this, i);
>         post_condition(i);
>       }

>   protected:
>       typedef void (*fn_t)(A*, int);
>       fn_t do_f;       // runtime customization, i.e. "virtual function"
>    };

>   struct B : A {  // starting from this point
>                   // one no longer accepts overrider for 'do_f'
>                   // Therefore, do_f is made private.

>       B()
>       {
>         do_f = B::do_f_impl;
>       }

>   private:
>     using A::do_f;   // restrict access for derived classes.

>     static void do_f_impl(A*, int);
>   };

> No class derived from B could override A::do_f with the access
> extriction (maybe except by fraud).

So what you are proposing is that I reimplement virtual functions by
hand anytime I need to enforce class invariants.  Or more realistically,
that I drop virtual functions systematically in favor of pointers to
functions (or pointers to member functions), since practically speaking,
the authors of the base class cannot know in advance that the derived
class will need to block further overriding.

Using separate agent classes is even easier and more robust (although it
involves additional runtime and space overhead).  And certainly more
readable.

> | They're totally irrelevant in the context of which I am speaking.

> No, they aren't.  Just like Mr. Jourdain was speaking prose all his
> life, you were using pointers to functions all the time.

When I want a pointer to an arbitrary function, I use pointers to
functions.  When I want a pointer to a member function, I use pointers
to member functions (and defend my use -- a lot of people don't like
them).  And when I want virtual functions, I use virtual functions.

I don't care about the implementation details.  I'm concerned about the
semantics.  And the semantics of a virtual function are NOT the same as
those of a pointer to a function.

> | It is possible to shield oneself by means of intermediate functional
> | objects.  This is very often done in Java, using inner classes.  The
> | tradeoffs are:

> |   - Intermediate functional objects lead to a lot of extra objects
> |     (with corresponding effects on memory use and run-time).  This
> |     is already somewhat visible in Java, where everything is a
> |     little, dynamically allocated object; the effect is
> |     proportionally worse in C++, because we normally have a lot less
> |     dynamically allocated objects.

> As showed above, no need for intermdiate class.

If you're willing to forego readability.

> This is the first time I'm reading you worrying about premature or
> micro-optimizations.

If the obvious, natural solution is also the fastest and has the least
space requirements...

In fact, I've been hit several times in the past by the costs of too
many very small objects.  In current C++, I'd use the extra objects,
perhaps with a custom allocator.  (In Java, they cost a lot less, thanks
to garbage collection.  Maybe some day in C++...)  But why should the
extra work be necessary.  There is a simple and proven solution which
works, if the language chooses to adopt it.  The results are easier to
read and understand.  AND result in faster and smaller code.

And to date, no one has posted the slightest argument against it.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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: kanze@gabi-soft.de (James Kanze)
Date: Mon, 30 Dec 2002 20:32:19 +0000 (UTC)
Raw View
petebecker@acm.org (Pete Becker) wrote in message
news:<3E0B0426.C6CFDFF0@acm.org>...
> James Kanze wrote:

> > Nobody is saying that all possible derivations from my class are
> > wrong, and should be forbidden.

> On the contrary: that is the title of this thread, and it is that idea
> that I object to. You're talking about something else, and it's
> important to keep that distinction clear.

That's true, and it isn't always easy to keep clear what position each
of the posters takes.  What we really have is two separate proposals:

Possibility to declare a function final, in order to prevent overriding:

    Advantages:
      - Enforcement of class invariants.
      - Optimization (maybe?)

    Disadvantages:
      - Possible loss of liberty to the authors of the derived class.

    IMHO, the "disadvantage" and the first advantage go hand in hand.  I
    don't want to give the derived class the liberty to break my class
    invariants:-).

    To date, I've not seen any real example of a programming technique
    which depends on this liberty.

Possibility to declare a class final, preventing all further
inheritance:

    Advantages:
      - Maybe some protection against an invalid swap, or something
        similar?  (I'm not sure -- my impression is that to avoid an
        invalid swap, you'd have to ban all inheritance, period.)

    Disadvantages:
      - Prevents some techniques of meta-programming, including some
        techniques already in use in Boost.
      - If the function level final is adopted, it's yet another
        overloading of a key word, along the lines of static, where the
        word means one thing in one context, and something different in
        another.

That would seem to be a short (although admittedly biaised) summary of
the positions so far.

If I can sum up, you, Dave Abrahams and Peter Dimov are radically
opposed to the second option, to the point of "over my dead body".  I'm
vaguely against it, partially because I trust DAve enough that when he
says there is a legitimate and important use, I believe him, and
partially because I'd rather keep open the possibility of having final
at the class level mean the same thing as at the function level -- that
all functions in the class are final (but that one can still inherit).
I don't think it is enormously useful at that level, but who knows.  If
it turns out that people do write a lot of classes in which all of the
virtual functions are final, we can always add it later, provided we
don't preempt the option by defining it now to mean something different.

My impression is that Dave and Peter are at least somewhat open to the
idea of a function level final, which I would very much like to see.  It
would be useful in my filtering streambuf classes, for example, where
the base class ensures the error handling, buffering and synchronization
issues, but the actual filtering takes place in yet a further
derivation -- which admittedly could be a delegate in most cases, at the
expense of a couple of extra little classes, probably dynamically
allocated, and a lot more code.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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: allan_w@my-dejanews.com (Allan W)
Date: Tue, 31 Dec 2002 02:16:51 +0000 (UTC)
Raw View
kanze@gabi-soft.de (James Kanze) wrote
(Comments about source-code coupling and the need to recompile)

allan_w@my-dejanews.com (Allan W) wrote
(Stunningly brilliant comments about different types of coupling,
and the differences between library authors and library clients :-)

Moderator added:
> ===================================== MODERATOR'S COMMENT:
> Please do remember in followups that this is posted to comp.std.c++;
> discussion of general software engineering that is not related to C++
> standardisation is better suited to other groups.
> ===================================== END OF MODERATOR'S COMMENT

One of the goals of the C++ language (at least, in Stroustrup's
original vision) is to support multiple styles of programming.
Since the language has a heavy influence on what styles we can
use, surely a discussion of various programming styles is relevant
to the changing standard?

James Kanze and I approach library development from different
perspectives. Hopefully the next C++ standard will address those
differences even more so than the current standard does (which is a
lot!).

---
[ 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: scottm@toast.net ("Scott Mayo")
Date: Thu, 2 Jan 2003 04:09:30 +0000 (UTC)
Raw View
"Pete Becker" <petebecker@acm.org> wrote in message
news:3E0B0426.C6CFDFF0@acm.org...
> James Kanze wrote:

> > Nobody is saying that all possible derivations from my class are wrong,
> > and should be forbidden.

> On the contrary: that is the title of this thread, and it is that idea
> that I object to. You're talking about something else, and it's
> important to keep that distinction clear.

Peter is right. I have been talking about a keyword which,
applied to a class, generates a fatal compile error if the
class is used as a basis for another. It seems to me that
while such a modifier is overkill for many purposes, it also
guarantees that, no matter how clever a misguided programmer
gets, they can't extend my class, screw things up, and blame me
for letting him do it. This is important when the misguided
soul is a paying customer who is too willing to Do The
Wrong Thing, and then tries to refuse payment until I make
*his* code work. Java has a way to curtail this. C++ could
as well.

Sometimes classes are meant to be internal to a design,
and attempts to mess with them, extend them or twerk
their internals, end in tears, or at least in support calls that I
have to answer. And completely hiding such classes from
external eyes can be a struggle. A single keyword that says,
succinctly and unarguably, that a given class is not to be touched,
spindled, folded, mutilated or reused, strikes me as a wonderful
thing. It makes plain business sense to be able to say "works
as is, unsupported if extended by anyone by the seller." Am
I really the only person here who could use such a thing?
I believe that people would be more willing to write
extendable code in general, if they had more control over
which bits were extended.

But I'll take what I can get. Anything I can use to limit any
misuse of any code I have to put into other people's hands
is a good thing. A limited 'final' is better than none.



---
[ 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: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Thu, 2 Jan 2003 04:10:18 +0000 (UTC)
Raw View
In article <7f2735a5.0212261434.5b81c795@posting.google.com>, Allan W
<allan_w@my-dejanews.com> writes
>So ciString is perfectly safe (and adopts all of the functionality
>of std::string, plus some more) so long as you don't ever try to
>    * Treat an array of ciString as if it was an array of std::string

And that means that it must not be used as an argument to a function
that takes a std::string &.  It is, IMHO, that which makes it dangerous.
It places too much responsibility on the user to avoid accidents.


>    * Delete a ciString via a pointer to std::string

--
ACCU Spring Conference 2003 April 2-5
The Conference you cannot afford to miss
Check the details: http://www.accuconference.co.uk/
Francis Glassborow      ACCU

---
[ 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: scottm@toast.net ("Scott Mayo")
Date: Thu, 2 Jan 2003 04:11:04 +0000 (UTC)
Raw View
"Electric Ninja" <noway@jose.dude> wrote in message
news:mK3O9.15545$%3.4317283@twister.neo.rr.com...
> > The original poster proposed three uses of "final":
> > (1) on classes, to prevent derivation
> > (2) on methods, to prevent overriding in derived classes
> > (3) on pointers, to prevent pointing to a derived class
> >     (and likewise for references)

> I can already see the future of this:
>
> Me pulling the hair out of my head because some genius decided to use
> "final" on a string class that I wanted to enhance.

Maybe he was far smarter than you are and *knows* why extending
his magic string class will break it?

Maybe you haven't purchased the right to extend that code?

Maybe some horrid Fortran code elsewhere *knows* that
sizeof(*myClassP) is exactly 44 bytes, and will die if it
isn't?

And granted, maybe he's an idiot, and did it for a stupid reason.
But if he's an idiot, you don't want to use his classes anyway.

I think it's fascinating that people continue to assume that
classes are *supposed* to be extendable. Classes are only a way
to wrap data and functionality. Extensibility is sometimes a part of
that, and other times it's a nonsensical idea. Really good extensibility
takes some thought. 90% of the classes I write, exist to get a job
done, and I make no attempt to insure they are extensible - in fact they
can contain code that makes extensibility awkward, in the interest of
performance. The other 10% are meant to be extended, and lots of
care goes into that: considered use of protected, virtual functions,
detailed comments so people can't go astray, careful checks to
make sure that the member functions cannot be misused by mortal
man, and all the rest.

What is wrong with putting up a "Keep Out" sign on swampy
ground? Honestly, I think some folk are overdosing on the
Object Oriented kool-aid. Sometimes, to mangle Freud,
a class is just a 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: rmaddox@isicns.com (Randy Maddox)
Date: Thu, 2 Jan 2003 04:11:28 +0000 (UTC)
Raw View
petebecker@acm.org (Pete Becker) wrote in message news:<3E0B435D.A0A7EF39@acm.org>...
> Randy Maddox wrote:
> >
> > I believe that you misstate the assumption here.  It is not that the
> > class designer assumes that no one else can maintain a contract, but
> > rather that the class designer knows best whether he/she has made
> > implementation assumptions that would cause problems if the class were
> > derived from.
> >
>
> In other words, the reason to block inheritance is to cover up
> implementation errors. Otherwise the contract would be sufficient.
>
> --
>
> Pete Becker
> Dinkumware, Ltd. (http://www.dinkumware.com)
>

IMHO it is hard to see how taking advantage of explicit design
assumptions to produce an implementation could be considered an error.
 Again, you are not arguing that there is no such thing as a leaf
class from which inheritance would not be appropriate.  As long as
such classes may exist then there is a demonstrable need for final.

Randy.

---
[ 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: rmaddox@isicns.com (Randy Maddox)
Date: Thu, 2 Jan 2003 04:11:36 +0000 (UTC)
Raw View
gdr@integrable-solutions.net (Gabriel Dos Reis) wrote in message news:<m31y44irpe.fsf@uniton.integrable-solutions.net>...
> rmaddox@isicns.com (Randy Maddox) writes:
>
> | hyrosen@mail.com (Hyman Rosen) wrote in message news:<1040658851.882926@master.nyc.kbcfp.com>...
> | > James Kanze wrote:
> | > > It's always possible to do anything.  One of the basic premises of
> | > > programming by contract is that a class is responsible for its
> | > > contract.
> | >
> | > Yes, exactly. Your class is responsible for its contract.
> | > My derived class is responsible for its contract. Your
> | > class is not responsible for the contract of my derived
> | > class. You seem to assume that no one beside yourself can
> | > maintain a contract, and therefore you won't let anyone
> | > derive from your class.
> | >
> |
> | I believe that you misstate the assumption here.  It is not that the
> | class designer assumes that no one else can maintain a contract, but
> | rather that the class designer knows best whether he/she has made
> | implementation assumptions that would cause problems if the class were
> | derived from.
>
> Do we have concrete examples for that scenario?

The simplest would be a concrete class such as Complex or Point where
size and efficiency are perfectly valid concerns and a virtual dtor
would not be acceptable.  Another example might be an internal pointer
that is used in a way that further inheritance might break, e.g.,
dereferenced and passed by value, which could result in object
slicing.  And other posters have already mentioned the issue of
maintaining internal class invariants, which may well not be visible
as part of the external contract.

>
> [...]
>
> | The fact that there are currently torturous idioms to work around the
> | lack of final in C++, idioms which were developed and disseminated at
> | some cost, would seem to indicate that there is indeed a real need for
> | final.
>
> The trouble is that no one has demonstrated that those putative
> problems are so recurring that it deserves another keyword (I've
> repeatedly seen allusions to class invariants with no croncrete
> examples).  On the other hand I've seen multiple references to its
> uses in Java.  I find that rather weak arguments.
>
> In case, you're wondering, I'm not against final or whatever it is
> called.  I want to understand the problems that keyword is supposed
> to solve, how pernicious they are and why they can't be solved with
> current C++ features.
>
> [...]
>
> | The counter argument that final is "dictatorial", "arrogant" or
> | "paternalistic" seems a bit weak to me.
>
> Oh, really?

Yes, really.  Given the level of control that C++ already provides to
the designer of a class, which has not here been characterized as
"dictatorial", "arrogant" or "paternalistic", it seems IMHO that
supporting final merely extends that control in one more small, but
sometimes important, way.  As with almost everything in C++, if you
don't need it or want it then don't use it.  But if others do need it
and want it, then why not let them use it?

Randy.

---
[ 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: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Thu, 2 Jan 2003 04:16:28 +0000 (UTC)
Raw View
In article <m31y44ff4p.fsf@uniton.integrable-solutions.net>, Gabriel Dos
Reis <gdr@integrable-solutions.net> writes
>petebecker@acm.org (Pete Becker) writes:
>
>> Francis Glassborow wrote:
>| >
>| > Considering the number of language implementors that read this
>| > newsgroup, perhaps one or more of them would consider issuing a warning
>| > when code derives from a class that has a non-virtual dtor.
>| >
>|
>| If they do they better make sure it can be reliably disabled.
>
>Strongly agreed.  From my experience, I find it useless.

About as useless as warnings for assignments in conditional expressions?
Any implementation that issues warnings should provide a mechanism for
switching them off. However those reading this news group should
remember that the vast majority of those who program in C++ are much
less skilled than they are.

--
ACCU Spring Conference 2003 April 2-5
The Conference you cannot afford to miss
Check the details: http://www.accuconference.co.uk/
Francis Glassborow      ACCU

---
[ 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: kanze@gabi-soft.de (James Kanze)
Date: Thu, 2 Jan 2003 06:27:33 +0000 (UTC)
Raw View
allan_w@my-dejanews.com (Allan W) wrote in message
news:<7f2735a5.0212261434.5b81c795@posting.google.com>...

> > Except for special cases: should std::iterator have a virtual
> > destructor?  (Actually, an empty, inline protected destructor
> > probably wouldn't hurt it.)

> If std::iterator had a virtual destructor, this would impact the speed
> of all iterators derived from it -- at least when used
> polymorphically.  (Virtual functions can only rarely be inlined.)

More importantly, it would affect the size of the iterator, and thus the
time it took to copy it.  Since iterators are normally copied by value,
this could have a significant impact.  I certainly do not think that it
should have a virtual destructor.

> An empty, inline, NON-virtual protected destructor would prevent
> anyone from instantiating std::iterator (as opposed to something
> derived from it). It wouldn't hurt anything else, but it wouldn't help
> anything, would it?

It would prevent anyone from deleting an object through a pointer to
std::iterator (except in a derived class).

Personally, I've never seen anyone do anything quite that stupid.  And
I've seen some pretty stupid things in my career.  But as I said, it
probably wouldn't hurt, and if it prevented one mistake, just once, it
would be worth it.  But I don't think that it would prevent enough
mistakes to make it worth my while to fight for it, or even to simply
take the time to write up a proposal.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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: kanze@gabi-soft.de (James Kanze)
Date: Thu, 2 Jan 2003 06:28:08 +0000 (UTC)
Raw View
dave@boost-consulting.com (David Abrahams) wrote in message
news:<uznqojymq.fsf@boost-consulting.com>...
> gdr@integrable-solutions.net (Gabriel Dos Reis) writes:
> > allan_w@my-dejanews.com (Allan W) writes:
> > | kanze@gabi-soft.de (James Kanze) wrote
> > | > In general, a non-virtual public destructor is a very good sign
> > | > that the class was not designed with inheritance in mind, and is
> > | > probably not a very good candidate for derivation.

> > | I'd say that a non-virtual public destructor is a very good sign
> > | that the class was not designed for polymorphism. Polymorphism is
> > | not the only use for derivation.

> > This is a far better formulation of the issue.  I'm always amazed to
> > see how many people (wrongly) equate inheritance with runtime
> > polymorphism. Still, when I consult standard texts (like
> > Stroustrup's or Koenig's) it is made pretty clear there that there
> > can be inheritance *without* run-time polymorphism.

> And there can also be run-time polymorphism without dynamic
> allocation.  I see no reason for a virtual destructor if, for example,
> operator new is private.

Or operator delete.

Nobody is denying that inheritance has a number of uses.  Realistically,
however, polymorphism is the most frequent, and when you use inheritance
for something else, you generally should document it carefully.

I find it incredible the amount of noise my parenthetical remark has
created.  I cited std::iterator as a good example of a class from which
you should inherit but which should not have a virtual destructor.  I
feel that it's a special case; it certainly doesn't work like the
majority of classes that I'm called to inherit from.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Thu, 26 Dec 2002 19:31:13 +0000 (UTC)
Raw View
Randy Maddox wrote:
>
> I believe that you misstate the assumption here.  It is not that the
> class designer assumes that no one else can maintain a contract, but
> rather that the class designer knows best whether he/she has made
> implementation assumptions that would cause problems if the class were
> derived from.
>

In other words, the reason to block inheritance is to cover up
implementation errors. Otherwise the contract would be sufficient.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Thu, 26 Dec 2002 19:31:37 +0000 (UTC)
Raw View
James Kanze wrote:
> I've mentionned the problem of maintaining class invariants more than
> once.  It's a real problem, which final helped solve a couple of times
> in Java.

What was the nature of the problem? Did you have co-workers
who derived from your classes and broke them?

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Thu, 26 Dec 2002 19:36:54 +0000 (UTC)
Raw View
James Kanze wrote:
>
> Nobody is saying that all possible derivations from my class are wrong,
> and should be forbidden.
>

On the contrary: that is the title of this thread, and it is that idea
that I object to. You're talking about something else, and it's
important to keep that distinction clear.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Thu, 26 Dec 2002 19:46:10 +0000 (UTC)
Raw View
rmaddox@isicns.com (Randy Maddox) writes:

| hyrosen@mail.com (Hyman Rosen) wrote in message news:<1040658851.882926@master.nyc.kbcfp.com>...
| > James Kanze wrote:
| > > It's always possible to do anything.  One of the basic premises of
| > > programming by contract is that a class is responsible for its
| > > contract.
| >
| > Yes, exactly. Your class is responsible for its contract.
| > My derived class is responsible for its contract. Your
| > class is not responsible for the contract of my derived
| > class. You seem to assume that no one beside yourself can
| > maintain a contract, and therefore you won't let anyone
| > derive from your class.
| >
|
| I believe that you misstate the assumption here.  It is not that the
| class designer assumes that no one else can maintain a contract, but
| rather that the class designer knows best whether he/she has made
| implementation assumptions that would cause problems if the class were
| derived from.

Do we have concrete examples for that scenario?

[...]

| The fact that there are currently torturous idioms to work around the
| lack of final in C++, idioms which were developed and disseminated at
| some cost, would seem to indicate that there is indeed a real need for
| final.

The trouble is that no one has demonstrated that those putative
problems are so recurring that it deserves another keyword (I've
repeatedly seen allusions to class invariants with no croncrete
examples).  On the other hand I've seen multiple references to its
uses in Java.  I find that rather weak arguments.

In case, you're wondering, I'm not against final or whatever it is
called.  I want to understand the problems that keyword is supposed
to solve, how pernicious they are and why they can't be solved with
current C++ features.

[...]

| The counter argument that final is "dictatorial", "arrogant" or
| "paternalistic" seems a bit weak to me.

Oh, really?

--
Gabriel Dos Reis, gdr@integrable-solutions.net

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Thu, 26 Dec 2002 20:48:41 +0000 (UTC)
Raw View
Francis Glassborow wrote:
>
> Considering the number of language implementors that read this
> newsgroup, perhaps one or more of them would consider issuing a warning
> when code derives from a class that has a non-virtual dtor.
>

If they do they better make sure it can be reliably disabled.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: allan_w@my-dejanews.com (Allan W)
Date: Thu, 26 Dec 2002 22:37:39 +0000 (UTC)
Raw View
kanze@gabi-soft.de (James Kanze) wrote
> In general, a non-virtual public destructor is a very good sign that the
> class was not designed with inheritance in mind, and is probably not a
> very good candidate for derivation.

I'd say that a non-virtual public destructor is a very good sign
that the class was not designed for polymorphism. Polymorphism
is not the only use for derivation.

    // This class identical to std::string, except that
    // relation operators ignore case.
    struct ciString : public std::string { ... };

With this class, code like this causes problems:

    std::string *x=new ciString("Kanze");
    std::string *y=new ciString("KANZE");

    std::cout << (*x) << " vs " << (*y) << std::endl; // Succeeds

    assert(*x = *y); // Fails -- using std::string::operator==
    delete x; // Fails -- std::string destructor not virtual
    delete y; // Fails -- std::string destructor not virtual

On the other hand, code like this works as expected:

    ciString *x=new ciString("Kanze");
    ciString *y=new ciString("KANZE");

    // Succeeds using std::string::operator<<
    std::cout << (*x) << " vs " << (*y) << std::endl;

    assert(*x = *y); // Succeeds, uses ciString::operator==
    delete x; // Succeeds
    delete y; // Succeeds

So ciString is perfectly safe (and adopts all of the functionality
of std::string, plus some more) so long as you don't ever try to
    * Treat an array of ciString as if it was an array of std::string
    * Delete a ciString via a pointer to std::string

> Except for special cases: should
> std::iterator have a virtual destructor?  (Actually, an empty, inline
> protected destructor probably wouldn't hurt it.)

If std::iterator had a virtual destructor, this would impact the speed
of all iterators derived from it -- at least when used polymorphically.
(Virtual functions can only rarely be inlined.)

An empty, inline, NON-virtual protected destructor would prevent anyone
from instantiating std::iterator (as opposed to something derived from
it). It wouldn't hurt anything else, but it wouldn't help anything,
would 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: philippe_mori@hotmail.com ("Philippe Mori")
Date: Fri, 27 Dec 2002 20:20:38 +0000 (UTC)
Raw View
>
> The problem is that it still only uses the static type of the object.
> Two objects can have the same static type, but different dynamic types.
> For that matter, swap normally creates a temporary of the static type;
> even if both objects have the same dynamic type, if this type is
> different from the static type, swap will fail.

Oooups... I forgot about that case. In practice, I do think that if the type
is dynamic, we would typically check the king of object anyway before
swapping them... And if objects are to used polymorphically, them we would
have pointers and would be able to swap pointers instead...

One way that we can try to prevent the uses of derived class is by using a
proxy/handle to the actual object and ensure that we cannot create (and
uses) those object directly...

Also if the class does not require to be created on the stack, one could
always make all constructors private (thus ensuring we cannot derive from
that class) and add a factory function (typically a static member) to create
those objects.


>
> Of course, all of this is totally irrelevant to the argument about
> final.  Final can't be made to help here, since the problem is just as
> present in cases where the inheritance is wanted.
>

Final would allows to solve the problem in some situations but not all. It
will works for object that we knows their type statically and also for type
that come from a pointer that is qualified with final...

Personally, I do like the idea of final pointer and I would even like more
pointer types (like __gc pointers in Visual C++.NET) and pointers to
array/non-array, stack objects, dynamic objects, shared objects...

That way if someone uses qualified pointers in the code, the compiler would
then be allowed to do far more validations... There would be an implicit
conversion to unqualified pointers. The conversion in the other direction
would be allowed only with a proper cast (maybe const_cast).

If qualified pointers are used, the compiler would be able to detect
deletion of a stack object, using the wrong form of delete (delete vs
delete[]) in many more cases.

Also it would be great if compilers that supports these new keywords would
have an option to warn about or prevent "requalifying" a pointer and another
options to prevent the use of unqualified pointers. That ways, the compiler
would be able to be more strict on new projects...


---
[ 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: allan_w@my-dejanews.com (Allan W)
Date: Fri, 27 Dec 2002 20:43:27 +0000 (UTC)
Raw View
===================================== MODERATOR'S COMMENT:
 Please do remember in followups that this is posted to comp.std.c++; discussion of general software engineering that is not related to C++ standardisation is better suited to other groups.


===================================== END OF MODERATOR'S COMMENT
kanze@gabi-soft.de (James Kanze) wrote
> If the only issue were optimization, I'd agree with you.  But IMHO,
> source code coupling is at least as an important an issue.  What happens
> when the pure forwarding function ceases to be a pure forwarding
> function?  Whether you take the function out of line, or modify the
> inline version, you still have to recompile all of the client code.
>
> On the other hand, I've gotten into the habit of providing explicit
> constructors, assignment and destructors, even when the compiler
> generated defaults will do.  Because the compiler generated defaults are
> inline, and if I change anything which means they won't do, all of the
> client code will be recompiled.

Not everyone here is writing library code with thousands of users.
In fact, most of us don't write library code at all; and many libraries
are used only by a handful of projects. In other words, sometimes we
can consider code to be decoupled based on the fact that source won't
change, even if we do need a recompile.

Certainly we want to minimize situations where a one-line change to
a header file requires most or all of a project to rebuild. But it
isn't an all-or-nothing proposition. I think it's okay to put an
inline function in a library that (for instance) implements business
rules, recognizing that business rules do change from time to time --
but not every week!

---
[ 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: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Fri, 27 Dec 2002 20:52:06 +0000 (UTC)
Raw View
allan_w@my-dejanews.com (Allan W) writes:

| kanze@gabi-soft.de (James Kanze) wrote
| > In general, a non-virtual public destructor is a very good sign that the
| > class was not designed with inheritance in mind, and is probably not a
| > very good candidate for derivation.
|
| I'd say that a non-virtual public destructor is a very good sign
| that the class was not designed for polymorphism. Polymorphism
| is not the only use for derivation.

This is a far better formulation of the issue.  I'm always amazed to
see how many people (wrongly) equate inheritance with runtime
polymorphism. Still, when I consult standard texts (like Stroustrup's
or Koenig's) it is made pretty clear there that there can be
inheritance *without* run-time polymorphism.

[...]

| > Except for special cases: should
| > std::iterator have a virtual destructor?  (Actually, an empty, inline
| > protected destructor probably wouldn't hurt it.)
|
| If std::iterator had a virtual destructor, this would impact the speed
| of all iterators derived from it -- at least when used polymorphically.
| (Virtual functions can only rarely be inlined.)

Well, I don't find that a strong argument: there is no reason why the
sole fact of having a virtual destructor implies that all its member
functions would become virtual.

However, the reasons why someone would turn the (perfectly) POD-class
std::iterator into a non-POD one are not given.  What is the purpose?

| An empty, inline, NON-virtual protected destructor would prevent anyone
| from instantiating std::iterator (as opposed to something derived from
| it). It wouldn't hurt anything else, but it wouldn't help anything,
| would it?

Well, *what* are you trying to prevent people from doing by forbidding
them to instantiate an std::iterator?  What kind os _real-world_
problem are you solving?

--
Gabriel Dos Reis, gdr@integrable-solutions.net

---
[ 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: "Philippe Mori" <philippe_mori@hotmail.com>
Date: Fri, 27 Dec 2002 15:06:20 CST
Raw View
> > The original poster proposed three uses of "final":
> > (1) on classes, to prevent derivation
> > (2) on methods, to prevent overriding in derived classes
> > (3) on pointers, to prevent pointing to a derived class
> >     (and likewise for references)
>
> I can already see the future of this:
>
> Me pulling the hair out of my head because some genius decided to use
> "final" on a string class that I wanted to enhance.
>

For case (1), we may be a bit less strict and still allows derivation but
prevent the use of the derived object as the base object (more or less like
private or protected inheritance). Maybe we should only allows private and
protected (implementation) inheritance. If conversion is need, then the
class would have to provide it explicitly (but we won't be able to returns a
"final Base *", just a "Base *"...

For case (2), there are other good uses of it. Say that a class derives from
those classes with the same virtual function but not related, one could uses
intermediate classes and final to ensure that the renamed functions would be
used by derived classes.

    class A { virtual void run(); };    // run() in A and B are not related
    class B { virtual void run(); };

    // Extra classes
    class A2 : public A {
        virtual void runA();
        final void run() { runA(); }    // Must now override runA() instead
of run()
    };
    class B2 : public B {
        virtual void runB();
        final void run() { runB(); }
    };

    // Class C derives from A2 and B2 instead of A and B...
    class C : public A2, public B2 {
        // virtual void run();    // This won't compile...
        virtual void runA();
        virtual void runB);
    };

Also in case (2), overriding would be allows for protected and private
inheritance... and as in case (1) it won't be possible to convert to "final
A" or "final B" so someone could also prevent the uses of derived classes...

Case (3) does not seems to cause any problem for me except that we needs
some rules for conversions and we may also want some other qualifiers...

---
[ 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: usenet_cpp@lehrerfamily.com (Joshua Lehrer)
Date: Fri, 27 Dec 2002 21:13:08 +0000 (UTC)
Raw View
gdr@integrable-solutions.net (Gabriel Dos Reis) wrote in message news:<m31y44irpe.fsf@uniton.integrable-solutions.net>...

> In case, you're wondering, I'm not against final or whatever it is
> called.  I want to understand the problems that keyword is supposed
> to solve, how pernicious they are and why they can't be solved with
> current C++ features.
>

from my perspective, it can make function calls much more efficient,
avoiding virtual dispatch.  If a class or method is marked as final,
then the methods can be called directly.  The common solution proposed
is simply call the method directly, obj->sub::method(), but this
assumes that the consumer knows which methods it can call directly.
Another problem with this approach is that if a method were to be
marked final, you would still need to modify your entire client code
base to get the benefit.  Finally, this solution doesn't allow you to
easily write generic code that calls method, regardless of whether or
not it is final.

joshua lehrer
factset research systems

---
[ 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: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Fri, 27 Dec 2002 22:23:32 +0000 (UTC)
Raw View
petebecker@acm.org (Pete Becker) writes:

| Francis Glassborow wrote:
| >
| > Considering the number of language implementors that read this
| > newsgroup, perhaps one or more of them would consider issuing a warning
| > when code derives from a class that has a non-virtual dtor.
| >
|
| If they do they better make sure it can be reliably disabled.

Strongly agreed.  From my experience, I find it useless.

--
Gabriel Dos Reis, gdr@integrable-solutions.net

---
[ 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: kanze@gabi-soft.de (James Kanze)
Date: Thu, 26 Dec 2002 09:17:07 +0000 (UTC)
Raw View
petebecker@acm.org (Pete Becker) wrote in message
news:<3E03B84E.5B9F02B7@acm.org>...
> "James Kuyper Jr." wrote:

> > Pete Becker wrote:
> > ....
> > > Sure, if someone does it. The problem is that people present the
> > > outline for a discussion as if it were complete and
> > > conclusive. And oddly enough, these demonstrations always ending
> > > up supporting the position of the person who presents them.

> > So, could you provide an example of what form the missing details
> > would take, if they were present? All I can tell from what you've
> > said so far is that something you think should be there is missing.

> I've asked a couple of times for concrete examples of problems that
> arose because of "inappropriate" inheritance and could have been
> prevented by final. Nobody gave any.

I've mentionned the problem of maintaining class invariants more than
once.  It's a real problem, which final helped solve a couple of times
in Java.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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: rmaddox@isicns.com (Randy Maddox)
Date: Thu, 26 Dec 2002 16:40:18 +0000 (UTC)
Raw View
hyrosen@mail.com (Hyman Rosen) wrote in message news:<1040658851.882926@master.nyc.kbcfp.com>...
> James Kanze wrote:
> > It's always possible to do anything.  One of the basic premises of
> > programming by contract is that a class is responsible for its
> > contract.
>
> Yes, exactly. Your class is responsible for its contract.
> My derived class is responsible for its contract. Your
> class is not responsible for the contract of my derived
> class. You seem to assume that no one beside yourself can
> maintain a contract, and therefore you won't let anyone
> derive from your class.
>

I believe that you misstate the assumption here.  It is not that the
class designer assumes that no one else can maintain a contract, but
rather that the class designer knows best whether he/she has made
implementation assumptions that would cause problems if the class were
derived from.

No one in this thread has yet argued that there is no such thing as a
leaf class from which further derivation is not appropriate.  And that
is the case in which final would have its best application.  Yes, it
might be misused, but we could scarcely have a programming language at
all if we eliminated every feature that might be misused.  Pointers
would surely be the first to go.  :-)

The fact that there are currently torturous idioms to work around the
lack of final in C++, idioms which were developed and disseminated at
some cost, would seem to indicate that there is indeed a real need for
final.  It's not like anyone is twisting your arm to use it if you
don't want or need it.

The counter argument that final is "dictatorial", "arrogant" or
"paternalistic" seems a bit weak to me.  Surely we can do better than
merely casting aspersions if there really are any strong technical
arguments against.

Randy.

---
[ 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: allan_w@my-dejanews.com (Allan W)
Date: Thu, 26 Dec 2002 18:30:42 +0000 (UTC)
Raw View
kanze@gabi-soft.de (James Kanze) wrote
> It's always possible to do anything.

You're saying that there is no such thing as an insolvable problem?
Perhaps a bit more broad than you intended. Carry this to absurdity:

  * Write a program that prints out a list of customers that were
    NOT added to the database
  * Write a general solution to the Turing problem
  * Lossless compression/decompression of ANY data at all, such
    that if the original data is 8 bytes or more, the compressed
    data is at least 1 byte smaller (including any "dictionary"
    needed for decompression)

I submit that all of these are MUCH harder than getting authors
of derived classes to honor class invariants. Plus, presumably anyone
using your class as a base, prefers to see the original functionality
continue to work correctly...

---
[ 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: noway@jose.dude (Electric Ninja)
Date: Thu, 26 Dec 2002 18:34:01 +0000 (UTC)
Raw View
> The original poster proposed three uses of "final":
> (1) on classes, to prevent derivation
> (2) on methods, to prevent overriding in derived classes
> (3) on pointers, to prevent pointing to a derived class
>     (and likewise for references)

I can already see the future of this:

Me pulling the hair out of my head because some genius decided to use
"final" on a string class that I wanted to enhance.

---
[ 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: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Thu, 26 Dec 2002 19:24:07 +0000 (UTC)
Raw View
kanze@gabi-soft.de (James Kanze) writes:

[...]

| > The former is of no immediat interest to me.  So I'll concentrate on
| > the latter.
|
| > In C++ there are at least two ways to cutomize at run-time an object
| > behaviour:
| >    (1) pointer to function
| >    (2) virtual member function
|
| > With (1), on has almost total control on what is going on.  Semantics
| > of (2) means, among other things: virtual once, virtual forever.
|
| I'm not quite sure I understand you.  What do pointers to functions have
| to do with anything?

Because virtual functions, implementing dynamic binding, are
essentially pointers to functions.  And those are in essence what you
do.  Therefore, before going on requesting a keyword to revert from
(2) to (1) in the middle of implementation, it seems appropriate to
reconsider the issue in its original or abstract setting.

With virtual functions, the compiler automatically sets the pointers
with the appropriate addresses, in the appropriate classes.  And that,
each time the compilers sees an overriding function.

What you seems to want is to have a way to tell the compiler to
accept no more overrider, starting from a point in the class
hierarchy.

Now, let's see how you can achieve the same effect in current C++.
The ingredients are:
  (1) pointer to function; and
  (2) accessiibility.

With pointer to function, you implement dynamic binding and with
control access you restrict/forbid access for derrived classes,
therefore prevents any further run-time customization.

Suppose we have a class A that wants to implement a function that may
be "finalized" latter in the class hierarchy.  You're known to use
design-by-contract in the sense that you make your virtual function
protected and have the public function non-virtual that calls it.

   struct A {

      void f(int i)    // calls do_f
      {
        pre_condition(i);
        do_f(this, i);
        post_condition(i);
      }

  protected:
      typedef void (*fn_t)(A*, int);
      fn_t do_f;       // runtime customization, i.e. "virtual function"
   };

  struct B : A {  // starting from this point
                  // one no longer accepts overrider for 'do_f'
                  // Therefore, do_f is made private.

      B()
      {
        do_f = B::do_f_impl;
      }

  private:
    using A::do_f;   // restrict access for derived classes.

    static void do_f_impl(A*, int);
  };

No class derived from B could override A::do_f with the access
extriction (maybe except by fraud).

| They're totally irrelevant in the context of which I am speaking.

No, they aren't.  Just like Mr. Jourdain was speaking prose all his
life, you were using pointers to functions all the time.

| It is possible to shield oneself by means of intermediate functional
| objects.  This is very often done in Java, using inner classes.  The
| tradeoffs are:
|
|   - Intermediate functional objects lead to a lot of extra objects (with
|     corresponding effects on memory use and run-time).  This is already
|     somewhat visible in Java, where everything is a little, dynamically
|     allocated object; the effect is proportionally worse in C++, because
|     we normally have a lot less dynamically allocated objects.

As showed above, no need for intermdiate class.  This is the first
time I'm reading you worrying about premature or micro-optimizations.


[...]

| > Your argumentation lets me under the impression that you're using (2)
| > where you should have been using (1) and discover latter that you want
| > a new keyword in order to revert to (1).
|
| I don't see any way that pointers to functions (nor pointers to member
| functions) could be used to solve the problem.

See above.

--
Gabriel Dos Reis, gdr@integrable-solutions.net

---
[ 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: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Thu, 26 Dec 2002 19:28:38 +0000 (UTC)
Raw View
In article <d6651fb6.0212230826.58b65697@posting.google.com>, James
Kanze <kanze@gabi-soft.de> writes
>In general, a non-virtual public destructor is a very good sign that the
>class was not designed with inheritance in mind, and is probably not a
>very good candidate for derivation.  Except for special cases: should
>std::iterator have a virtual destructor?  (Actually, an empty, inline
>protected destructor probably wouldn't hurt it.)

Considering the number of language implementors that read this
newsgroup, perhaps one or more of them would consider issuing a warning
when code derives from a class that has a non-virtual dtor.

I suspect that it has more a flavour of QoI than language feature.

--
ACCU Spring Conference 2003 April 2-5
The Conference you cannot afford to miss
Check the details: http://www.accuconference.co.uk/
Francis Glassborow      ACCU

---
[ 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: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Thu, 26 Dec 2002 19:30:12 +0000 (UTC)
Raw View
kanze@gabi-soft.de (James Kanze) writes:

[...]

|  A
| limited form of final, however, does something that cannot otherwise be
| done in the language,

This remains to be proved.

--
Gabriel Dos Reis, gdr@integrable-solutions.net

---
[ 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: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Thu, 26 Dec 2002 19:30:26 +0000 (UTC)
Raw View
kanze@gabi-soft.de (James Kanze) writes:

| petebecker@acm.org (Pete Becker) wrote in message
| news:<3E03B84E.5B9F02B7@acm.org>...
| > "James Kuyper Jr." wrote:
|
| > > Pete Becker wrote:
| > > ....
| > > > Sure, if someone does it. The problem is that people present the
| > > > outline for a discussion as if it were complete and
| > > > conclusive. And oddly enough, these demonstrations always ending
| > > > up supporting the position of the person who presents them.
|
| > > So, could you provide an example of what form the missing details
| > > would take, if they were present? All I can tell from what you've
| > > said so far is that something you think should be there is missing.
|
| > I've asked a couple of times for concrete examples of problems that
| > arose because of "inappropriate" inheritance and could have been
| > prevented by final. Nobody gave any.
|
| I've mentionned the problem of maintaining class invariants more than
| once.  It's a real problem, which final helped solve a couple of times
| in Java.

It is seems to be a problem because the wrong tool was used from the
outset; no because the language is lacking final.

--
Gabriel Dos Reis, gdr@integrable-solutions.net

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Thu, 26 Dec 2002 19:30:45 +0000 (UTC)
Raw View
James Kanze wrote:
>
> petebecker@acm.org (Pete Becker) wrote in message
> news:<3E03B84E.5B9F02B7@acm.org>...
> > "James Kuyper Jr." wrote:
>
> > > Pete Becker wrote:
> > > ....
> > > > Sure, if someone does it. The problem is that people present the
> > > > outline for a discussion as if it were complete and
> > > > conclusive. And oddly enough, these demonstrations always ending
> > > > up supporting the position of the person who presents them.
>
> > > So, could you provide an example of what form the missing details
> > > would take, if they were present? All I can tell from what you've
> > > said so far is that something you think should be there is missing.
>
> > I've asked a couple of times for concrete examples of problems that
> > arose because of "inappropriate" inheritance and could have been
> > prevented by final. Nobody gave any.
>
> I've mentionned the problem of maintaining class invariants more than
> once.  It's a real problem, which final helped solve a couple of times
> in Java.
>

Sigh. I've also mentioned maintaining class invariants. But you've been
talking about a different notion than the one that started this thread,
i.e. a different one from the one I was talking about.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: brangdon@cix.co.uk (Dave Harris)
Date: Fri, 20 Dec 2002 16:58:09 +0000 (UTC)
Raw View
hyrosen@mail.com (Hyman Rosen) wrote (abridged):
> But derived classes could still override it if they wanted,
> using virtual or not.
>
>     class vector_base {
>      public:
>          virtual int size() const = 0;
>          // ...
>      };
>
>      class vector : public vector_base {
>      public:
>          /* "final" */ int size() const;
>          // ...
>      };
>
>      class instrumented_vector : public vector {
>      public:
>          virtual int size() const;
>          // ...
>      }

This could mean two things. Either instrumented_vector::size() overrides
vector_base::size(), or it is a new function which does not override. In
the latter case, it would get a new slot in the vtable (or whatever the
implementation uses).

Either way I think it is a bit confusing, especially for public
inheritance. We have:

    instrumented_vector v1;
    vector &v2 = v1;
    int s1 = v1.size();
    int s2 = v2.size();

where the last two function calls call different functions despite using
the same name, argument list and object.

It's similar to the situation where vector doesn't inherit from
vector_base. C++ allows us to make a function virtual in a derived class
despite it being non-virtual in the base class. This is an unpleasant
situation but I suppose "final" doesn't make it worse. It can be useful
and safe where the inheritance is private.

I am inclined to say that once the middle class, vector, has made size()
non-virtual, that slot in the vtable is frozen and instrumented_vector has
to use a new slot for its size(). This provides a way for vector to hide
its heritage.

At first I thought this was too fragile. If the base class, vector_base,
changed its declaration of size() slightly (eg by making it non-const),
then presumably vector::size() wouldn't match it and instrumented_vector
could override it again. Now I think that this kind of thing is a reason
to allow "final" to apply to an entire class. With:

      final class vector : public vector_base { ... }

there is no chance of a subclass of vector accidentally overriding
vector_base's virtuals, no matter what signatures are used.

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."

---
[ 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: brangdon@cix.co.uk (Dave Harris)
Date: Fri, 20 Dec 2002 16:58:26 +0000 (UTC)
Raw View
hyrosen@mail.com (Hyman Rosen) wrote (abridged):
> I think the keyword should be '~virtual' rather than 'final'.

Interesting suggestion. It makes sense for functions. I am not sure about
class-wide final. Eg:

    class Derived: private final Base {
        // ...
    };

says that all of Base's virtual functions are made non-virtual in Derived.
This seems fairly useful to me, and with "final" the meaning is clear.
However, with:

    class Derived: private ~virtual Base {
        // ...
    };

the existing overloading of "virtual" catches us.

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."

---
[ 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: nid_oizo@yahoo.com_removethe_ (Nicolas Fleury)
Date: Fri, 20 Dec 2002 19:49:16 +0000 (UTC)
Raw View
Hyman Rosen wrote:
> Francis Glassborow wrote:
>
>> The adjective 'arrogant' has been used in this thread, I might add
>> 'paternalistic'. Could we stick to the technical merits of a proposal.
>
>
> We are debating a feature that will enable programmers to be
> arrogant and paternalistic.

Doesn't seem very objective to me.   If I make a small class hierarchy I
decide where "virtuality" of my member functions begins.  With
"finality", I also decide where it ends.  Suppose one of my leaf class
introduces a new member function that I judge would be error-prone to
derive from.  Am I arrogant or paternalistic because I decide to not put
it virtual?  The same logic can apply to some overriden member
functions; you just don't provide virtuality when it doesn't make sense.
  Note that I'm talking about member functions finality, not classes; I
think putting a destructor final (and let warnings do the rest) should
be enough.

Regards,

Nicolas Fleury

---
[ 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: alain@miniussi.net (Alain Miniussi)
Date: Sun, 22 Dec 2002 07:11:15 +0000 (UTC)
Raw View
James Kanze wrote:

>> > I repeat: the optimization issue is a red herring with
>> > regards to final.  The real issue is whether you think the
>> > author of a class should be in charge of his class
>> > invariants, or whether you think that anyone who might want
>> > to derive from the class should be permitted to violate the
>> > invariants arbitrarily.  Put that way, it sounds like the
>> > answer is obvious.  To me it is, but surprisingly, I've run
>> > into not a few people who insist that all functions should
>> > be virtual.  Always.  Still, in C++, I think the general
>> > trend is to recognize that at least some functions shouldn't
>> > be redefinable.  Not for optimization reasons, but because
>> > we want to be able to write correct code.  This is, after
>> > all, one of the motivations (mine, at least) behind
>> > forbidding public functions to be virtual in many cases.
>
>> This is one (valid) tactique, but these are not everybody's
>> choices (of course, establish which one is more common really
>> depends on the sample you choose).
>
> What is one valid tactique?

To avoid public virtual function in order to protect your code.

Alain

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Sun, 22 Dec 2002 07:11:43 +0000 (UTC)
Raw View
"James Kuyper Jr." wrote:
>
> Pete Becker wrote:
> ....
> > Sure, if someone does it. The problem is that people present the outline
> > for a discussion as if it were complete and conclusive. And oddly
> > enough, these demonstrations always ending up supporting the position of
> > the person who presents them.
>
> So, could you provide an example of what form the missing details would
> take, if they were present? All I can tell from what you've said so far
> is that something you think should be there is missing.
>

I've asked a couple of times for concrete examples of problems that
arose because of "inappropriate" inheritance and could have been
prevented by final. Nobody gave any.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Sun, 22 Dec 2002 07:11:45 +0000 (UTC)
Raw View
kanze@gabi-soft.de (James Kanze) writes:

[...]

| > I believe that one of the key issues is about the real (not
| > supposed) contribution of "final" in solving that problem.
|
| Well, I can only guess for C++.  For Java, I know from concrete
| experience that we regularly declared about half the functions
| in the derived class final, in order to ensure our class
| invariants.

As stated elsewhere in this thread, that happens because most of those
functions should not have been virtual in the first place.  No?

--
Gabriel Dos Reis,       gdr@integrable-solutions.net

---
[ 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: kanze@gabi-soft.de (James Kanze)
Date: Mon, 23 Dec 2002 11:32:59 +0000 (UTC)
Raw View
hyrosen@mail.com (Hyman Rosen) wrote in message
news:<1040328601.47724@master.nyc.kbcfp.com>...
> James Kanze wrote:
> > You don't agree that ensuring class invariants
>  > is a problem for C++ code?

> You are making the assumption that no user of the class will be able
> to extend it without breaking the invariants. Some of us believe that
> it should be up to the class users to decide this, not the class
> designers. This is the "break my code" versus "break your code"
> distinction.

> Since I can derive a class and have the overriders just call their
> base functions, it's always possible to have a derived class which
> doesn't break invariants.

It's always possible to do anything.  One of the basic premises of
programming by contract is that a class is responsible for its
contract.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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: kanze@gabi-soft.de (James Kanze)
Date: Mon, 23 Dec 2002 11:33:00 +0000 (UTC)
Raw View
gdr@integrable-solutions.net (Gabriel Dos Reis) wrote in message
news:<m34r983xog.fsf@uniton.integrable-solutions.net>...
> kanze@gabi-soft.de (James Kanze) writes:

> [...]

> | > I believe that one of the key issues is about the real (not
> | > supposed) contribution of "final" in solving that problem.

> | Well, I can only guess for C++. For Java, I know from concrete
> | experience that we regularly declared about half the functions in
> | the derived class final, in order to ensure our class invariants.

> As stated elsewhere in this thread, that happens because most of those
> functions should not have been virtual in the first place. No?

Is this your experience with Java?  It isn't mine.

I suspect that it depends on the application domain (and programming
style), but we regularly used final in derived classes, to ensure that
we defined the last override.  In our case, we were developing a GUI
framework, which had to process a number of events, via callback
interfaces.  Obviously, the functions must be virtual in the callback
interface.  On the other hand, how the events were handled, at least in
the first instance, was part of OUR class contract.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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: kanze@gabi-soft.de (James Kanze)
Date: Mon, 23 Dec 2002 11:33:02 +0000 (UTC)
Raw View
alain@miniussi.net (Alain Miniussi) wrote in message
news:<v06vttj31pd5b6@corp.supernews.com>...
> James Kanze wrote:

> >> > I repeat: the optimization issue is a red herring with regards to
> >> > final.  The real issue is whether you think the author of a class
> >> > should be in charge of his class invariants, or whether you think
> >> > that anyone who might want to derive from the class should be
> >> > permitted to violate the invariants arbitrarily.  Put that way,
> >> > it sounds like the answer is obvious.  To me it is, but
> >> > surprisingly, I've run into not a few people who insist that all
> >> > functions should be virtual.  Always.  Still, in C++, I think the
> >> > general trend is to recognize that at least some functions
> >> > shouldn't be redefinable.  Not for optimization reasons, but
> >> > because we want to be able to write correct code.  This is, after
> >> > all, one of the motivations (mine, at least) behind forbidding
> >> > public functions to be virtual in many cases.

> >> This is one (valid) tactique, but these are not everybody's choices
> >> (of course, establish which one is more common really depends on
> >> the sample you choose).

> > What is one valid tactique?

> To avoid public virtual function in order to protect your code.

I'm not quite sure I understand.  Even if the virtual function is
private, all of the derived classes can override it.  Making it private
doesn't protect against this.

By making it private, and calling through a non-virtual public
interface, you can, of course, enforce a certain number of things at
run-time.  In this case, however, the issue is more one of the class
invariants in the derived class, and not of the contract in the base
class.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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: Mon, 23 Dec 2002 16:46:09 +0000 (UTC)
Raw View
James Kanze wrote:
> It's always possible to do anything.  One of the basic premises of
> programming by contract is that a class is responsible for its
> contract.

Yes, exactly. Your class is responsible for its contract.
My derived class is responsible for its contract. Your
class is not responsible for the contract of my derived
class. You seem to assume that no one beside yourself can
maintain a contract, and therefore you won't let anyone
derive from your 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: philippe_mori@hotmail.com ("Philippe Mori")
Date: Mon, 23 Dec 2002 18:19:49 +0000 (UTC)
Raw View
For a compile-time solution, I would suggest to do something like:

template <typename T> class Test { };

template <typename T, typename U>
void swap(T &, U&) {
    // Do something that will ensure that the code do not compile...
(compile-time assertion)
    // See book like "Modern C++ Design" for more complete solutions...
    Test<T> t(Test<U>());
}

template <typename T>
void swap(T &t1, T &t2)
{
    // Implementation here...
}


---
[ 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: fjh@students.cs.mu.OZ.AU (Fergus Henderson)
Date: Mon, 23 Dec 2002 18:24:29 +0000 (UTC)
Raw View
petebecker@acm.org (Pete Becker) writes:

>Fergus Henderson wrote:
>>
>> >> Final *will* help here, because I can just add "final", and continue
>> >> on with the rest of my programming task. I can be confident that my
>> >> invariants won't be broken.
>> >
>> >Danger, danger, context switch. The original assertion was that
>> >
>> >>> If the Array class is used in
>> >>> a large number of places, it may be difficult to determine whether there
>> >>> is any code which derives from Array.
>>
>> This was in the context of adding a new member function such as swap()
>> to the Array class.  `final' will help in that situation.  Adding
>> final and recompiling [...]
>
>Recompiling certainly won't help if the program is not in a compilable
>state, which is the reason you gave for not being able to use a browser.

That was one of *two* reasons that I gave.

Recompiling *straight away* won't help, sure.   But I didn't mean that.
You can add final straight away and continue on with the rest of your
programming task.  If there was a problem, the compiler will remind you
later, when you eventually get around to recompiling.

--
Fergus Henderson <fjh@cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.

---
[ 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: comp.std.c++_2002-12-23@nmhq.net (Niklas Matthies)
Date: Mon, 23 Dec 2002 18:32:53 +0000 (UTC)
Raw View
On 2002-12-23 16:46, Hyman Rosen <hyrosen@mail.com> wrote:
> James Kanze wrote:
>> It's always possible to do anything.  One of the basic premises of
>> programming by contract is that a class is responsible for its
>> contract.
>
> Yes, exactly. Your class is responsible for its contract. My derived
> class is responsible for its contract. Your class is not responsible
> for the contract of my derived class. You seem to assume that no one
> beside yourself can maintain a contract, and therefore you won't let
> anyone derive from your class.

Deriving from a class sets up a contract between the base part and the
derived part of the derived class. The derived part is a client of the
base part, very much like other code that is using some instance of the
base class. The base class needs to maintain its contract towards the
derived part in just the same manner as it does towards other client
code. Deriving from a class doesn't (or shouldn't) suddenly invalidate
that class' contract.

-- Niklas Matthies

---
[ 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: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Mon, 23 Dec 2002 18:41:23 +0000 (UTC)
Raw View
fjh@students.cs.mu.OZ.AU (Fergus Henderson) writes:

| petebecker@acm.org (Pete Becker) writes:
|
| >Fergus Henderson wrote:
| >>
| >> >> Final *will* help here, because I can just add "final", and continue
| >> >> on with the rest of my programming task. I can be confident that my
| >> >> invariants won't be broken.
| >> >
| >> >Danger, danger, context switch. The original assertion was that
| >> >
| >> >>> If the Array class is used in
| >> >>> a large number of places, it may be difficult to determine whether there
| >> >>> is any code which derives from Array.
| >>
| >> This was in the context of adding a new member function such as swap()
| >> to the Array class.  `final' will help in that situation.  Adding
| >> final and recompiling [...]
| >
| >Recompiling certainly won't help if the program is not in a compilable
| >state, which is the reason you gave for not being able to use a browser.
|
| That was one of *two* reasons that I gave.
|
| Recompiling *straight away* won't help, sure.   But I didn't mean that.
| You can add final straight away and continue on with the rest of your
| programming task.

Huh?!?

Is final a keyword supposed to magically turn a non-compilable program
into a compilable one?  If so, how?
I'm aksing because I can't find a description for that magic property
in the proposed semantics.

--
Gabriel Dos Reis, gdr@integrable-solutions.net

---
[ 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: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Mon, 23 Dec 2002 23:28:30 +0000 (UTC)
Raw View
kanze@gabi-soft.de (James Kanze) writes:

| gdr@integrable-solutions.net (Gabriel Dos Reis) wrote in message
| news:<m34r983xog.fsf@uniton.integrable-solutions.net>...
| > kanze@gabi-soft.de (James Kanze) writes:
|
| > [...]
|
| > | > I believe that one of the key issues is about the real (not
| > | > supposed) contribution of "final" in solving that problem.
|
| > | Well, I can only guess for C++. For Java, I know from concrete
| > | experience that we regularly declared about half the functions in
| > | the derived class final, in order to ensure our class invariants.
|
| > As stated elsewhere in this thread, that happens because most of those
| > functions should not have been virtual in the first place. No?
|
| Is this your experience with Java?

I must admit that what has been reported to that effect matches my
(admitely limited) experience with Java.

|  It isn't mine.
|
| I suspect that it depends on the application domain (and programming
| style), but we regularly used final in derived classes, to ensure that
| we defined the last override.  In our case, we were developing a GUI
| framework, which had to process a number of events, via callback
| interfaces.  Obviously, the functions must be virtual in the callback
| interface.  On the other hand, how the events were handled, at least in
| the first instance, was part of OUR class contract.

So let's tackle the technical issues.  Are-we going to discuss final for
Java or putative final for C++?

The former is of no immediat interest to me.  So I'll concentrate on
the latter.

In C++ there are at least two ways to cutomize at run-time an object
behaviour:
   (1) pointer to function
   (2) virtual member function

With (1), on has almost total control on what is going on.
Semantics of (2) means, among other things: virtual once, virtual
forever.

Your argumentation lets me under the impression that you're using (2)
where you should have been using (1) and discover latter that you want
a new keyword in order to revert to (1).

--
Gabriel Dos Reis,       gdr@integrable-solutions.net

---
[ 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: kanze@gabi-soft.de (James Kanze)
Date: Thu, 26 Dec 2002 08:48:21 +0000 (UTC)
Raw View
hyrosen@mail.com (Hyman Rosen) wrote in message
news:<1040658851.882926@master.nyc.kbcfp.com>...
> James Kanze wrote:
> > It's always possible to do anything.  One of the basic premises of
> > programming by contract is that a class is responsible for its
> > contract.

> Yes, exactly. Your class is responsible for its contract.  My derived
> class is responsible for its contract. Your class is not responsible
> for the contract of my derived class. You seem to assume that no one
> beside yourself can maintain a contract, and therefore you won't let
> anyone derive from your class.

The fact that someone derives from my class does not free my class from
its responsibilities to live up to the contract.  Presumably, there are
additional clauses in the contract of the derived class, which it is the
derived classes responsibility to meet, but these don't concern me.

If a class cannot live with the contract of my class, it shouldn't
derive from my class, because that contract will still be there.  If a
class can live with the contract of my class, there is no reason why it
shouldn't derive from my class, but there is also no reason why it
should be able to override functionality which is essential for my class
to maintain its contract.

Nobody is saying that all possible derivations from my class are wrong,
and should be forbidden.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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: kanze@gabi-soft.de (James Kanze)
Date: Thu, 26 Dec 2002 08:57:05 +0000 (UTC)
Raw View
philippe_mori@hotmail.com ("Philippe Mori") wrote in message
news:<s30N9.7922$cN3.1363302@news20.bellglobal.com>...

> For a compile-time solution, I would suggest to do something like:

> template <typename T> class Test { };

> template <typename T, typename U>
> void swap(T &, U&) {
>     // Do something that will ensure that the code do not compile...
> (compile-time assertion)
>     // See book like "Modern C++ Design" for more complete solutions...
>     Test<T> t(Test<U>());
> }

> template <typename T>
> void swap(T &t1, T &t2)
> {
>     // Implementation here...
> }

The problem is that it still only uses the static type of the object.
Two objects can have the same static type, but different dynamic types.
For that matter, swap normally creates a temporary of the static type;
even if both objects have the same dynamic type, if this type is
different from the static type, swap will fail.

Of course, all of this is totally irrelevant to the argument about
final.  Final can't be made to help here, since the problem is just as
present in cases where the inheritance is wanted.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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: kanze@gabi-soft.de (James Kanze)
Date: Thu, 26 Dec 2002 09:01:05 +0000 (UTC)
Raw View
gdr@integrable-solutions.net (Gabriel Dos Reis) wrote in message
news:<m37ke0y4ip.fsf@uniton.integrable-solutions.net>...
> kanze@gabi-soft.de (James Kanze) writes:
> | gdr@integrable-solutions.net (Gabriel Dos Reis) wrote in message
> | news:<m34r983xog.fsf@uniton.integrable-solutions.net>...
> | > kanze@gabi-soft.de (James Kanze) writes:

> | > [...]

> | > | > I believe that one of the key issues is about the real (not
> | > | > supposed) contribution of "final" in solving that problem.

> | > | Well, I can only guess for C++. For Java, I know from concrete
> | > | experience that we regularly declared about half the functions
> | > | in the derived class final, in order to ensure our class
> | > | invariants.

> | > As stated elsewhere in this thread, that happens because most of
> | > those functions should not have been virtual in the first
> | > place. No?

> | Is this your experience with Java?

> I must admit that what has been reported to that effect matches my
> (admitely limited) experience with Java.

> |  It isn't mine.

> | I suspect that it depends on the application domain (and programming
> | style), but we regularly used final in derived classes, to ensure
> | that we defined the last override.  In our case, we were developing
> | a GUI framework, which had to process a number of events, via
> | callback interfaces.  Obviously, the functions must be virtual in
> | the callback interface.  On the other hand, how the events were
> | handled, at least in the first instance, was part of OUR class
> | contract.

> So let's tackle the technical issues.  Are-we going to discuss final
> for Java or putative final for C++?

All I'm saying is that I found one particular effect of final in Java
very useful for enforcing class invariants, and that I've seen nothing
to suggest that this utility wouldn't transfer to C++ -- the languages
are practically identical in the particular context of which I am
speaking.

> The former is of no immediat interest to me.  So I'll concentrate on
> the latter.

> In C++ there are at least two ways to cutomize at run-time an object
> behaviour:
>    (1) pointer to function
>    (2) virtual member function

> With (1), on has almost total control on what is going on.  Semantics
> of (2) means, among other things: virtual once, virtual forever.

I'm not quite sure I understand you.  What do pointers to functions have
to do with anything?  They're totally irrelevant in the context of which
I am speaking.

It is possible to shield oneself by means of intermediate functional
objects.  This is very often done in Java, using inner classes.  The
tradeoffs are:

  - Intermediate functional objects lead to a lot of extra objects (with
    corresponding effects on memory use and run-time).  This is already
    somewhat visible in Java, where everything is a little, dynamically
    allocated object; the effect is proportionally worse in C++, because
    we normally have a lot less dynamically allocated objects.

  - The lifetime of the intermediate functional objects must be
    managed.  This isn't normally particularly difficult, but it does
    mean more code, and thus, more places where you can accidentally
    make a mistake.  (This is one place where garbage collection would
    really help.)

  - Declaring the intermediate objects is more complex in C++ than in
    Java; because C++ doesn't have inner classes, you have to manage the
    address of the main object manually.  My experience would suggest
    that this is a misfeature of Java; having name lookup search through
    several different classes unrelated by inheritance doesn't help
    readability at all.  The feature was no doubt introduced precisely
    to facilitate such small forwarding objects, however.  Personnaly,
    we found using final instead of inner classes resulted in more
    readable code.

> Your argumentation lets me under the impression that you're using (2)
> where you should have been using (1) and discover latter that you want
> a new keyword in order to revert to (1).

I don't see any way that pointers to functions (nor pointers to member
functions) could be used to solve the problem.  I do recognize that
introducing intermediate objects could.  As solutions go, however, I
consider it heavy and awkward, when a simpler solution could exist.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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, 26 Dec 2002 09:02:16 +0000 (UTC)
Raw View
Niklas Matthies wrote:
> Deriving from a class sets up a contract

The base class specifies what its methods do,
and what overridden methods must do. For some
reason, there are people who feel that no one
but the original class author is capable of
meeting the second condition, and so people
must be forbidden from deriving from the class.

This from a language without bounds checking.

---
[ 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: kanze@gabi-soft.de (James Kanze)
Date: Thu, 26 Dec 2002 09:04:11 +0000 (UTC)
Raw View
francis.glassborow@ntlworld.com (Francis Glassborow) wrote in message
news:<4SyfiCBswuA+EwnW@robinton.demon.co.uk>...
> In article <7f2735a5.0212191628.48fbda62@posting.google.com>, Allan W
> <allan_w@my-dejanews.com> writes
> >But certainly it makes sense -- not neccesarily for a "one liner"
> >(after all, you can put some very complicated calculations on one
> >line!) but for functions I would call "Trivial". To me, a trivial
> >function is one that returns data already stored in an
> >easily-accessed variable.

> How about a pure forwarding function which will generate zero code?
> Such things as functions that ensure const correctness which simply
> allow the compiler to call the const version and return a non-const
> reference/pointer based on one of the parameters.

> Of course a modern linker can probably do that optimisation for you
> but I cannot see that it is wrong (or premature) to do it explicitly.

If the only issue were optimization, I'd agree with you.  But IMHO,
source code coupling is at least as an important an issue.  What happens
when the pure forwarding function ceases to be a pure forwarding
function?  Whether you take the function out of line, or modify the
inline version, you still have to recompile all of the client code.

That said, in practice, I do use inline in cases where I feel the source
code coupling isn't relevant.  In templates, for example, at least while
waiting for export (not even "coming soon" for most of the compilers I'm
forced to use).  Or for specific cases where the basic design or coding
guidelines say it has to be a simple forwarding function -- in a number
of places I've worked, there has been a guideline along the lines that
an operator overload should always simply forward to a named function,
and when that convention is used, most of my operator overloads are
inline.

On the other hand, I've gotten into the habit of providing explicit
constructors, assignment and destructors, even when the compiler
generated defaults will do.  Because the compiler generated defaults are
inline, and if I change anything which means they won't do, all of the
client code will be recompiled.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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: kanze@gabi-soft.de (James Kanze)
Date: Thu, 26 Dec 2002 09:04:18 +0000 (UTC)
Raw View
llewelly.@@xmission.dot.com (llewelly) wrote in message
news:<86lm2kheqk.fsf@Zorthluthik.foo>...
> kanze@gabi-soft.de (James Kanze) writes:

> > llewelly.@@xmission.dot.com (llewelly) wrote in message
> > news:<86el8hjkcw.fsf@Zorthluthik.foo>...
> > > kanze@gabi-soft.de (James Kanze) writes:
> > > [snip]
>  [snip]
> > > I strongly suspect most of those supporting final have not thought
> > > of preserving class invariants, and are trying to solve a quite
> > > different problem, which your suggestion does not address. (I
> > > agree that the problem you describe is real, and could be solved
> > > by the mechanism you suggest - I just think most of the other
> > > posters here are not thinking about it when they think of
> > > 'final'.)

> > What other use could it have in C++?

> I suspect many many features of C++ have become part of some idiom
> that no designer of said feature considered.

We are talking about potential uses of a new feature.  Certainly, any
feature may have uses nobody has thought of yet, but we shouldn't add
features to C++ just because they might have a use in the future that we
can't think of now.

I'm generally pretty sceptical of new features in the language.  A
limited form of final, however, does something that cannot otherwise be
done in the language, and can be used to improve code robustness.
That's a current use, based on my actual experience with Java, and not
some speculation about what might be possible someday.

> > I base my comments on my experience in Java -- in user code, all of
> > the use we made of final was to preserve class invariants.

> The issues with non-virtual destructors, assignment operators, etc, do
> not arise in Java (so far as I know). If C++ got a final that
> prevented all public inheritance (as opposed to your suggestion of
> only preventing the overriding of virtual functions), I am nearly
> certain it would be used for classes with non-virtual destructors,
> etc, to prevent the problems I mentioned.

And given the examples by Dave and Peter where this would cause
problems, it is probably a reason why this type of final should not be
adopted.

> [snip]
> > > By use of such things as non-virtual destructors, assignment
> > > operators, swap members, cast operators, etc, it is possible to
> > > create a class (call it Base) such that a class Derived which is
> > > derived from Base has some error-prone behavior when used
> > > polymorphicly. The classic example is deleteing an object with a
> > > non-virtual destructor, using a pointer that is not of the
> > > object's exact type. I believe these kinds of classes are in fact
> > > the primary bone of contention between the want-finals and the
> > > not-want-finals.

> > I want final, but I don't see any real problem here.

> You want a different kind of final. You want something I'll call
> do_not_override. It is more specific (and probably better suited to
> C++) than a naive importation of java's final.

That IS Java's final, at least when it is applied to functions.  I
certainly don't think that we should follow Java's mistake of
overloading a single keyword to mean different things in different
contexts.  Although they can obviously point to static in both C and C++
as precedence, one static is enough.

> I'm unsure of how (un)common the probablems I mention are. I used to
> see them all the time when I did C++ tutoring in school. I mention
> them because they are frequently cited examples of why C++ should have
> a means for preventing inheritance. I don't think preventing
> inheritance is a good way to solve those problems; I don't see them
> often in my work as a programmer.

I'll admit that I've never seen a problem in C++ because someone derived
from a class which wasn't designed for it.  That doesn't mean that it
doesn't happen, of course.  But I've seen real problems where people
thought that they'd be too clever, and override my overriding of some
virtual function.  I certainly wouldn't categorize it as C++'s number
one problem, but it is a problem which could be easily avoided.

> Perhaps they are best solved by education. But it's silly to expect
> non-virtual destructor like problems to not be raised in a discussion
> about final, and of course people have reason to ask for a
> language-supported mechanism for solving these problems. (Hyman's
> mention of Ada's two types of pointers, the kind which supports
> polymorphism, and the kind that doesn't, is an intriguing
> possibility.)

> [snip]
> > Before this thread, I'd have probably said OK to a final blocking
> > inheritance anyway;

> Then this thread has done some good.

It always does good when people discuss openly.  While a few people seem
to have very set opinions: C++ must have final, or C++ can never have
final, most of the posters have real, concrete reasons for their
opinions, based on actual experience.

    [...]
> > Maintaining class invariants is essential in order to avoid breaking
> > my code.

> And in the case of the non-virtual destructor problem, it could be
>     argued that code which uses a derivitive of such a class is
>     relying on an invariant the base class does not pretend to
>     preserve.

In general, a non-virtual public destructor is a very good sign that the
class was not designed with inheritance in mind, and is probably not a
very good candidate for derivation.  Except for special cases: should
std::iterator have a virtual destructor?  (Actually, an empty, inline
protected destructor probably wouldn't hurt it.)

In all cases, you have to weigh what you get against what you loose.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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: kanze@gabi-soft.de (James Kanze)
Date: Wed, 18 Dec 2002 17:15:28 +0000 (UTC)
Raw View
scottm@toast.net ("Scott Mayo") wrote in message
news:<3dfcdb0d@news.toast.net>...

> > Could someone please provide a summary of the general view of the
> > pro group.  What is "final"?  What kinds of inheritance does it
> > block?  Which standard library classes should be marked "final"?
> > When should "final" be used?

> final (as I see it) would look like Java's final.

That's just one possibility.  The essential aspect is to prevent
overriding functions that shouldn't be overridden.

> It would serve as notice that a class may not be inherited from (no
> is-a usage at all)

Which is it: no inheritance, or no isA usage?  As the anti-final posters
here have pointed out, there are significant uses for inheritance other
than isA.

> and it would allow possible optimizations of the code.

Optimizations which a (very) good optimizer could find anyway.

> It might be used to indicate that the class is not written in a
> way that makes general derivation safe; it might indicate that this is
> my code not your code, and I don't want you extending it because you
> haven't arranged for that right with me, or it might see use when
> every possible optimization is needed.  The latter is the main
> justification for it in Java.

I don't think I've ever seen final used for optimization in Java.  The
most frequent use at the class level is simply to document that the
class really should have value semantics, but since Java doesn't support
this...  There is a proposal (from Gosling) concerning optimization, but
it involves a new keyword (immutable, I think): not only must the class
be final, but it must have no mutating (non-const in C++ speak)
functions.

> I don't know of a hue and cry against 'final' in Java, though I
> suppose opponents could claim this is because final is so necessary
> (Java performs hideously without it) that it has ceased to be seen as
> evil.

Java performs very well, thank you.  I've seen benchmarks where it beats
C++.  Without using final.

The typical Java implementation is somewhat different than most C++
implementations in that it does the final compilation at link time.  So
the optimizer has much more knowledge of the global context.  Also,
because it actually takes place at run-time, it can make a number of
simplifying assumptions, placing run-time assertions concerning the
assumptions at the start of the block.  If the assert fails, it has
enough information to recompile on the fly using less strict assertions.

Good C++ compilers work in a similar manner (except for differing
everything to runtime).  If the profiler output indicates that all of
the virtual function calls are in fact to one specific instance, the
linker can then inline that instance.  The only difference with regards
to Java is that the linker must immediately generate the pessimistic
alternative as well, with a run-time check to choose between them.

None of this, of course, requires final.

> In summary, 'final' is cheap to implement, has prior art in Java, and
> represents a clear way to specify something that can be specified now,
> but using idioms which are obscure (maybe not to people here, but to
> many C++ programmers who are not language wonks.)

Sorry, but *I* don't know how to do the equivalent of declaring a
function final.  And with no false modesty, I suspect that if I don't
know how to do it, there are probably other C++ programmers who don't
know either.

> Admittedly, huge numbers of programmers wouldn't use it, the same way
> that lots of programmers don't mess with const and private today, but
> the ones that would, probably would have sound reasons for it.

> I also see some advantages in code linting. "Class is not final;
> destructor is not virtual.. does this class support inheritance?"
> could make people think through designs more carefully in early stages
> of development. Heaven knows C++ has enough subtle snares to make such
> checks valuable.

> As far as I can make out, the argument against it is that someone
> might deliberately make a class impossible to inherit from, when they
> shouldn't have. But they can do that anyway, with obscure
> tricks. Given that final has value as an optimization AND as a way to
> warn people off of making gruesome mistakes, and given that it's
> already possible to sabotage inheritance (in ugly ways), it's hard for
> me to see objections.

> People who write perfect classes that are always perfectly extensible
> will never need it. For the rest of us, I see advantages.

The argument against it, if I understand it correctly, is that there are
uses for inheritance other than simple isA, with the overriding of
virtual functions.  That correctly done, these uses are safe.  And that
they potentially involve just about every possible class.

The important thing is that my functions aren't overridden.  Without
that, I can't really ensure my class invariants.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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: fjh@students.cs.mu.OZ.AU (Fergus Henderson)
Date: Wed, 18 Dec 2002 17:17:42 +0000 (UTC)
Raw View
petebecker@acm.org (Pete Becker) writes:

>Fergus Henderson wrote:
>>
>> petebecker@acm.org (Pete Becker) writes:
>>
>>  >Fergus Henderson wrote:
>>  >>
>>  >> petebecker@acm.org (Pete Becker) writes:
>>  >>
>>  >> >Fergus Henderson wrote:
>>  >> >>
>>  >> >> petebecker@acm.org (Pete Becker) writes:
>>  >> >>
>>  >> >> >Unless you're the user's mother it's not
>>  >> >> >your responsibility to try to make him into a better programmer.
>>  >> >>
>>  >> >> It is every class designer's responsibility to do their best
>>  >> >> to ensure that the classes that they design are easy to use,
>>  >> >> and hard to misuse.
>>  >> >
>>  >> >That was the goal of Pascal. Look how well it's succeeded.
>>  >>
>>  >> Pascal failed for other reasons.  Pascal was fundamentally flawed because
>>  >> it had a strict static type system with no dynamic typing, no polymorphism
>>  >> and no support for genericity.  Also, it lacked a standard module system.
>>  >> These factors made code reuse very difficult.
...
>Oh, I see: you're talking about standard Pascal, not the dialects that
>actually had some commercial success. Borland Pascal provides pretty
>much the same set of features as you outline above. It's a niche
>product.

Sure.  But Borland Pascal was a proprietry set of extensions to Pascal.
It only ran on one platform.  There was only one implementation.
There was no official international standard for Borland Pascal; the
language definition probably changed with every new release.  There was no
free software implementation.  Borland Pascal's success was linked to the
success of Borland: if you were implementing your application in Borland
Pascal, then you were betting your long-term success on the continuing
viability and success of Borland -- whose main competitor, Microsoft, was
a powerful and monopolistic company that controlled the underlying platform.
In short, if you were concerned with the long-term, it was a risky
proposition!

C, on the other hand, had an official ANSI standard in the works, and lots
of different implementations, including the free software GNU C compiler.
It ran on just about everything, and you could be sure that it could be
ported to just about anything without too much cost.  It started with
the backing of the corporate giant AT&T, rode on the back of Unix, and
was adopted by Microsoft.  It's success was not tied to the success of
any one company.

Pascal failed to standardize on a sufficiently expressive base language to
enable code reuse among different implementations.  Borland Pascal
solved the expressiveness problem, but had all the drawbacks of being
a single-source proprietry language.  C was better than both Pascal
and Borland Pascal because it had a subset that was expressive enough
to allow code reuse, but still portable.

--
Fergus Henderson <fjh@cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.

---
[ 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, 18 Dec 2002 17:18:51 +0000 (UTC)
Raw View
Scott Mayo wrote:
> I dislike Java too, but I'm not willing to dismiss
> an entire language out of hand. It turns out that Java has a structure
> roughly similar to C++ in terms of classes, and 'final' has the
> same semantics as it would in C++. 'final' solves a problem in
> Java (even if you don't agree that there is such a problem)

This has nothing to do with liking or disliking Java.
While the class structure of C++ and Java are roughly
similar, 'final' solves a problem for Java that exists
only in Java, at a place where the differences in class
structure show up. We don't agree that there is an
equivalent problem in C++, and therefore the presence
of 'final' in Java is not (useful) prior art for C++.

The problem for Java is that it has no object types,
only pointers to objects, and no non-virtual functions.
Therefore, to gain some of the advantages of inline and
direct function calls, that language needs a way to
bypass the virtual mechanism. In C++, you can just make
methods non-virtual.

---
[ 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: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Wed, 18 Dec 2002 20:27:35 +0000 (UTC)
Raw View
In article <1040226478.583165@master.nyc.kbcfp.com>, Hyman Rosen
<hyrosen@mail.com> writes
>The problem for Java is that it has no object types,
>only pointers to objects, and no non-virtual functions.
>Therefore, to gain some of the advantages of inline and
>direct function calls, that language needs a way to
>bypass the virtual mechanism. In C++, you can just make
>methods non-virtual.

Actually not entirely.

In Java all functions start as virtual and you can switch that off when
you so choose (imposing your will on those that wish to derive from your
class)

In C++ we start with functions being non-virtual, but once we switch on
virtual we have no way to switch it off again. Once we have started we
cannot stop.


--
Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ 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: Daniel.Miller@tellabs.com ("Dan'l Miller")
Date: Wed, 18 Dec 2002 20:53:51 +0000 (UTC)
Raw View
Hyman Rosen wrote:
> Scott Mayo wrote:
>
>> I dislike Java too, but I'm not willing to dismiss
>> an entire language out of hand. It turns out that Java has a structure
>> roughly similar to C++ in terms of classes, and 'final' has the
>> same semantics as it would in C++. 'final' solves a problem in
>> Java (even if you don't agree that there is such a problem)
>
>
> This has nothing to do with liking or disliking Java.
> While the class structure of C++ and Java are roughly
> similar, 'final' solves a problem for Java that exists
> only in Java,

   Since when does only Java have class invariants to enforce?  If a virtual
member-function in a C++ intended-to-be-leaf derived class participates in
enforcing a class invariant and if someone inappropriately overrides that
virtual function in a way which displaces that class-invariant enforcement, then
are you still claiming that there is no equivalent problem in C++?

> at a place where the differences in class
> structure show up. We don't agree that there is an
> equivalent problem in C++, and therefore the presence
> of 'final' in Java is not (useful) prior art for C++.
>
> The problem for Java is that it has no object types,
> only pointers to objects, and no non-virtual functions.

   The problem-space solved by final is present in any language which has
polymorphic member-functions.  The converse does not follow.  The problem is not
absent in languages which omit non-polymorphic member-functions.  Likewise, the
problem is not absent in languages which permit non-polymorphic member-functions.

> Therefore, to gain some of the advantages of inline and
> direct function calls, that language needs a way to
> bypass the virtual mechanism. In C++, you can just make
> methods non-virtual.

   If one makes the member-functions non-virtual in C++, then one removes the
possibility of polymorphism via that function at all inheritance levels.
Obviously, the problem-space solved by final is not how to make a
member-function nonpolymorphic at all inheritance levels.  Rather, the
problem-space solved by final is how to terminate the ability to further
polymorphically override (in further-derived classes) an already-overridden
polymorphic member-function (in a derived class), so that polymorphism for that
member-function is permitted at the more-ancestral levels of inheritance and so
that polymorphism for that member-function is prohibited at the more-descendent
levels of inheritance.

---
[ 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: fjh@students.cs.mu.OZ.AU (Fergus Henderson)
Date: Wed, 18 Dec 2002 20:54:14 +0000 (UTC)
Raw View
pdimov@mmltd.net (Peter Dimov) writes:
 >fjh@cs.mu.OZ.AU (Fergus Henderson) wrote:
 >> pdimov@mmltd.net (Peter Dimov) writes:
 >> >Derivation is almost never a mistake in itself, and the
 >> >posted example did not demonstrate a case where it is a mistake. The
 >> >swap member function would always work as intended. In some cases it
 >> >would leave a derived class in an inconsistent state, but the meaning
 >> >of "inconsistent" is defined by the design of the derived class and
 >> >not by the fact that it has been derived.
 >>
 >> Your statement "The swap member function would always work as intended"
 >> is wrong.  The "swap" member function would not work as intended if
 >> passed an object of a derived class with additional data members.  The
 >> intended meaning of "swap" is that it swap the values of the two objects.
 >> If passed an object of the derived class, it does not have that effect.
 >
 >"swap" will correctly swap the values of the two objects. The fact
 >that it the argument is a subobject, and not a complete object, is of
 >no concern to "swap" itself.

"The two objects" referred to in my definition above of what semantics
I intended for swap are the most derived objects referred to by
the parameters, not the base class sub-objects corresponding to the
parameters' static types.  If I had intended swap() to just swap the
base class sub-objects, I would have named it swap_subobjects().

Note that I wrote that code, so I get to define the intended semantics!

 >What is the postcondition of swap?

The postcondition of swap() is that the final value of the first
object is equivalent to the original value of the second object,
and vice versa.  (Since we're being pedentatic, I'll clarify that:
by "the first object", I mean the most derived object pointed to by the
`this' parameter, and by "the second object", I mean the most derived
object referred to by the other parameter.)

 >If you replace inheritance with
 >containment and invoke "swap" on the member, the effect would be the
 >same;

In that case, swap() would *correctly* swap the most derived objects
referred to by the parameter.  The behaviour is correct in the sense
that it matches my original intent (which I have clarified above).

 >you can't blame inheritance for "swap"'s alleged failure,
 >although you _could_ blame the sometimes undesirable derived to base
 >conversion.

The use of inheritence in this context means that swap()'s preconditions
can easily be accidentally violated due to this implicit conversion.
So I do put some of the blame for such failures on the derivation.
But I agree that inheritence alone is not *solely* responsible.

 >> However, you're right that it's not the derivation alone that causes the
 >> problem; it's derivation, plus passing a derived class object to the
 >> swap member function,
 >
 >Plus the fact that the derived class is broken when the base part is
 >modified.

The derived class may work fine when the base part is modified,
and yet the code will still be broken if it relies on the post-condition
of swap(), documented above, since that post-condition will not hold.

 >Many derived classes don't break in such situations. The
 >derived class may have no state, or it may have state that is
 >independent of the state of the base class.

Having no (extra) state is OK.  In that case the call to swap()
won't break anything.

But if the derived class has state which is independent of the base class
state, then it's still broken, at least semantically, since the call
to swap() does not have the effect intended by the author of swap().
The caller of swap() is relying on implementation details of swap()
rather than the semantics that was intended, implied (IMHO) by its name,
and documented above.  Now, it may happen that the code "works", but
it's still broken.

 >> Clearly it must be OK to rely on the post-condition of a function that
 >> you've called.  All of our programming relies on that.  So that only
 >> leaves two things which could be wrong: the derivation, or passing
 >> the derived class object to the swap member function.
 >
 >True. But even if you blame the derivation (and this is too strict as
 >the user may never call swap), not all possible derivations are wrong.

Agreed.  But if you step back far enough, there are always other ways
to express the same thing.  You never *need* to use inheritence.

 >> The original poster proposed three uses of "final":
 >>  (1) on classes, to prevent derivation
 >>  (2) on methods, to prevent overriding in derived classes
 >>  (3) on pointers, to prevent pointing to a derived class
 >>      (and likewise for references)
 >
 >I have already shown how you can implement (3) in current C++: use a
 >template, and a static assertion. It doesn't cover all cases, but
 >neither would (3), unfortunately.
 >
 >void f(X final const & x);
 >
 >void g(X const & x) { g(x); }
                       ^          I think you mean "f" here?
 >
 >g(Y());

Presuming you mean f(x) rather than g(x) there,
I'd be inclined to say that this call should result in a compile error --
it should not be legal to convert an `X &' to `X final &'.

Describing this properly in the standard might require some
significant changes, since the committee made the unfortunate
decision to describe things in terms of "lvalue of type X"
rather than "value to type X &"... I guess if we want to keep the
existing terminology style then we might need a new term "final lvalue",
to denote lvalues whose dynamic type is known to be the same as their
static type.  The derived-to-base conversion would result in a non-final
lvalue.  Initializing a reference of type "final X &" with a non-final
lvalue would not be allowed.

--
Fergus Henderson <fjh@cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.

---
[ 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: fjh@students.cs.mu.OZ.AU (Fergus Henderson)
Date: Wed, 18 Dec 2002 20:54:16 +0000 (UTC)
Raw View
allan_w@my-dejanews.com (Allan W) writes:

>So, you would not only add "final" to the list of "cv-qualifiers"
>(which I supose would now be "cvf-qualifiers"), but you would also
>use them to overload calls to member functions?

Sure, why not?

--
Fergus Henderson <fjh@cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.

---
[ 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: Daniel.Miller@tellabs.com ("Dan'l Miller")
Date: Wed, 18 Dec 2002 20:54:42 +0000 (UTC)
Raw View
David Abrahams wrote:
> fjh@cs.mu.OZ.AU (Fergus Henderson) writes:
>
>
>>pdimov@mmltd.net (Peter Dimov) writes:
>>
>> >
>> >class X
>> >{
>> >public:
>> >
>> >  virtual void f() = 0;
>> >
>> >protected:
>> >
>> >  ~X() {}
>> >};
>> >
>> >class impl: public X
>> >{
>> >public:
>> >
>> >  virtual void f() {}
>> >};
>> >
>> >boost::shared_ptr<X> px(new impl);
>>
>>I don't understand.  Won't that result in undefined behaviour
>>when px's destructor is called?
>
>
> No. This is not your father's shared_ptr<T>.

   Oh, yet another library-based smart pointer!  'Tis a good thing that
somebody's father's shared_ptr<T> did not get standardized yet for time
immemorial if the research & development engines are still chugging away in new
& surprising ways.  How will we know when this newly-born shared_ptr<T> is The
One (i.e., the one for standardization to serve our needs for years or decades)?
  Or will it be Son Of Shared_ptr or Grandson of Shared_ptr which is The One?  I
sure hope that we pick the right one to live with long-term.

---
[ 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: alain@miniussi.net (Alain Miniussi)
Date: Wed, 18 Dec 2002 20:55:09 +0000 (UTC)
Raw View
James Kanze wrote:
> scottm@toast.net ("Scott Mayo") wrote in message
> news:<3dfcdb0d@news.toast.net>...
>> and it would allow possible optimizations of the code.
>
> Optimizations which a (very) good optimizer could find anyway.

Not a very strong argument, IMO. Inlining of non virtual function
is a lot easier then inlining of virtual functions. easier to the
point that the former is done in practice, not the later. Even
considering cross module inlining. With the same argument, you
don't need "inline" (I am not saying we'd get as much benefit as
with inline, I am just questioning the argument).

Of course, "with tomorow's compilers..."

>> It might be used to indicate that the class is not written in a
>> way that makes general derivation safe; it might indicate that this is
>> my code not your code, and I don't want you extending it because you
>> haven't arranged for that right with me, or it might see use when
>> every possible optimization is needed.  The latter is the main
>> justification for it in Java.
>
> I don't think I've ever seen final used for optimization in Java.  The
> most frequent use at the class level is simply to document that the
> class really should have value semantics, but since Java doesn't support
> this...  There is a proposal (from Gosling) concerning optimization, but
> it involves a new keyword (immutable, I think): not only must the class
> be final, but it must have no mutating (non-const in C++ speak)
> functions.
>
>> I don't know of a hue and cry against 'final' in Java, though I
>> suppose opponents could claim this is because final is so necessary
>> (Java performs hideously without it) that it has ceased to be seen as
>> evil.
>
> Java performs very well, thank you.  I've seen benchmarks where it beats
> C++.  Without using final.

For non numeric applications ?
I remember final making a difference in Java, it was a few years back
(anyway, I have seen benchmarks showing purely symbolic languages
being faster than C, and I have seen how people did the benchmarks
for Java perf, those people cannot be trusted :-).


Alain


---
[ 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: alain@miniussi.net (Alain Miniussi)
Date: Wed, 18 Dec 2002 21:00:09 +0000 (UTC)
Raw View
Hyman Rosen wrote:

> Alain Miniussi wrote:
>> So, you tell me, how high is the price of a virtual call ? :-)
>> Compared to say, an inlined function ? (if it's final it can
>> be inlined).
>> With "final", I can adapt.
>
> Once you have profiled your code and determined that a
> particular virtual call is the problem, and at the call
> site you know what class you actually have,

This looks like the argument usually made for inline, which
calls for some comments, since there is a lot of pratice with
inline::

 - That's one set of possible requirements, in practice it
is not the most used (actually, I have seen profiling impacting
on algorithm, on temporary removal, never on inline). And
sometime for good reasons.

 - It might be interesting to notice that if that rule was
as popular as it's claimed, then we would have an inline-like
keyword for the call site (inline *this* call if *this* call
is the problem), instead of just one for the declaration (inline
*all* calls if *this* call is the problem). Your solution
does not follow common practice for inline, not sure if it
is good or bad, but if you want to adapt the inline "official"
guideline to this problem, you do not get the result you
are describing.

 - I am using libraries, writen by competent engineers, with
inline functions in them. The authors didn't came here to
profile my code, how do they know those function would a
bottleneck in my application ? Or is there another respectable
way of reach the conclusion that a method should be declared
inline ?

> you can
> replace that call with p->Class::func() and bypass the
> virtual mechanism.

Or I can have final, which won't fail the day someone overrides
the method, might improve things for all call sites (since I have
the price in one place, I might as well get the most of it) won't
have to be re-evaluated each time my application change in a
way that can move bottlenecks around and, perhaps most importantly,
help the optimizer dealing with it without putting a hack in my
code (note that the optimizer is platform dependant, as can
be the costs of different flavors of function call).

Again, I don't care that much about final :-)

Regards.

Alain


---
[ 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, 18 Dec 2002 21:52:49 +0000 (UTC)
Raw View
Dan'l Miller wrote:
>   Since when does only Java have class invariants to enforce?

Since when do we assume that overriding members will
break invariants? It sounds like the same old argument
about class designers exerting fascistic control over
users, dressed up in fancier language. It's the same
"break my code" versus "break your code" dichotomy.

If you give the control freaks 'final', then derivers
will have no chance to make their changes, correct or
not. If you don't, then the onus is on the derivers
to do things correctly, which is as it should be.

 > the problem-space solved by final is how to terminate the
 > ability to further polymorphically override

Some of us don't think this is a problem that needs
solving. Some of us think that permitting class makers
to do this *is* the problem.

---
[ 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: pdimov@mmltd.net (Peter Dimov)
Date: Wed, 18 Dec 2002 21:52:53 +0000 (UTC)
Raw View
pdimov@mmltd.net (Peter Dimov) wrote in message news:<7dc3b1ea.0212180559.758dff3d@posting.google.com>...
[...]
> void f(X final const & x);
>
> void g(X const & x) { g(x); }

Oops, this should have been { f(x); }

>
> g(Y());

An interesting twist would be to disallow final-adding conversions,
treating absence of final as a cv-qualifier. With such an addition, it
would be possible to write a non-slicing swap. I'm not sure whether
'final' is the appropriate keyword, or whether this has anything to do
with the original 'final' proposal. :-)

---
[ 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, 18 Dec 2002 22:06:56 +0000 (UTC)
Raw View
Alain Miniussi wrote:
> This looks like the argument usually made for inline

I expect James Kanze can tell you what he considers
best practice with respect to that :-) I doubt that
it includes willy-nilly inlining of everything.

Aside from the minor semantic difference of requiring
that an inline function be defined everywhere it's used,
inline is merely a hint by the designer to the compiler
that inlining of the function would be a good idea. In
particular, it doesn't restrict users in any way. On the
other hand, final is a demand, not a suggestion, and
users have no way of overriding the demand.

 > might improve things for all call sites

But you're talking about call sites that operate directly
on derived-class references. To me, that seems unusual.
We're talking about adding a keyword which will turn a
virtual call into a direct one, at call sites which receive
a pointer or reference to a derived class instead of to a
base class. Since such an optimization is useful only when
the call does nothing or nearly nothing, it seems like such
a remote circumstance that there's no worth in doing 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Daniel.Miller@tellabs.com ("Dan'l Miller")
Date: Wed, 18 Dec 2002 22:13:31 +0000 (UTC)
Raw View
Hyman Rosen wrote:
> Dan'l Miller wrote:
>
>>   Since when does only Java have class invariants to enforce?
>
>
> Since when do we assume that overriding members will
> break invariants?

   Since I explicitly posited it as a given in the design scenario which I was
discussing.  I left no wiggle room in this regard.  Please color within the lines.

---
[ 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, 18 Dec 2002 22:26:42 +0000 (UTC)
Raw View
Francis Glassborow wrote:
> Once we have started we cannot stop.

Correct, and the question becomes whether the
ability to stop is important enough to warrant
the inclusion of final into C++, given that
many of us think that it will be more misused
than used appropriately.

---
[ 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, 18 Dec 2002 22:27:23 +0000 (UTC)
Raw View
Peter Dimov wrote:
>>void f(X final const & x);
>>void g(X const & x) { f(x); }
>>g(Y());

Hmm. As usual, we find that Ada has been there,
done that. In Ada, there is a distinction made
between declaring things to have a specific type
and declaring them to have "classwide" type.

Dispatching happens only on objects or pointers
of classwide type, not on objects of actual type.
(That is, if you have a class Base, and an object
of type Base or pointer to Base, the methods
invoked are those of Base only. If you have an
object or pointer of type Base'class, then
dispatching will happen if the the object is of
derived type.)

---
[ 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: allan_w@my-dejanews.com (Allan W)
Date: Wed, 18 Dec 2002 23:10:28 +0000 (UTC)
Raw View
petebecker@acm.org (Pete Becker) wrote
> I've heard several different versions of final mentioned here,
> some of which are clearly different from Java. The ones that aren't
> clearly different aren't detailed enough to make that determination.

> I am not aware of any evidence showing that final would improve the
> performance of C++ programs. Are you?

It probably depends on which version of "final" you refer to, but:

    class Foo : public Bar {
        // ...
    public:
        virtual void foofunc();
    };

    // ...

    void Process(Foo&f) {
        Foo e;
        e.foofunc();
        f.foofunc();
    }

As written, the call to e.foofunc() can be optimized to call foofunc
directly, rather than using the virtual table -- because we know that
e really is a Foo object. On the other hand, the call to f.foofunc
must be a virtual call, because f is only a reference -- it could
actually refer to some object type derived from Foo.

With final (either on class Foo or on Foo::foofunc), both calls can
be optimized the same way. If class Foo is final, we know that nothing
can be derived from Foo(note1) -- and therefore f is also a Foo object.
If function foofunc is final, we know that derived classes cannot
redefine the function, and therefore we can assume that the virtual
table resolves to Foo:foofunc.

(note1) Assumes that there is no "override" that lets you derive
from an otherwise-final class.

Come on, Pete. You must see this too -- and with over 250 messages in
this thread, surely I'm not the first to point this out.

---
[ 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: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Thu, 19 Dec 2002 00:37:37 +0000 (UTC)
Raw View
In article <1040246143.60616@master.nyc.kbcfp.com>, Hyman Rosen
<hyrosen@mail.com> writes
>Francis Glassborow wrote:
>> Once we have started we cannot stop.
>
>Correct, and the question becomes whether the
>ability to stop is important enough to warrant
>the inclusion of final into C++, given that
>many of us think that it will be more misused
>than used appropriately.

The adjective 'arrogant' has been used in this thread, I might add
'paternalistic'. Could we stick to the technical merits of a proposal.
--
Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ 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: alain@miniussi.net (Alain Miniussi)
Date: Thu, 19 Dec 2002 00:37:44 +0000 (UTC)
Raw View
Hyman Rosen wrote:

> Alain Miniussi wrote:
>> This looks like the argument usually made for inline
>
> I expect James Kanze can tell you what he considers
> best practice with respect to that :-) I doubt that
> it includes willy-nilly inlining of everything.

I remember reading that his principles
were relaxed when it came to one liner where the
inlined code would be shorter than the call.

Please note that I did not judge what were the
"best" practices, I was just pointing that a lot
of people, some of them respectables, used other
rule than the one you mentioned on a regular basis.
I am not even judging if it is a good thing or not,
just that this is a pratice to consider.

> Aside from the minor semantic difference of requiring
> that an inline function be defined everywhere it's used,

Actually, I don't think it is.

> inline is merely a hint by the designer to the compiler
> that inlining of the function would be a good idea. In
> particular, it doesn't restrict users in any way. On the
> other hand, final is a demand, not a suggestion, and
> users have no way of overriding the demand.

It is correct that final could be overused in the name
of optimization, maybe with worse concequences than
an overuse of inline.

But, back to the Visitor DP, one constraint is that the
visited hierarchy should be stable enough, since addition
of new leaf class vould invalidate the Visitor code. So in
this case, final would help enforcing a constraint.

I think that other exemple of non optimisation example
have been provided.

I would be personally more than reluctant in using
final for optimisation purpose. But you can get a benefit
as side effect in cases where you have a design alibi.
I also suspect that if I know that the call cannot
be virtual for some reason, then maybe that reason
would justify the use on final.

>  > might improve things for all call sites
>
> But you're talking about call sites that operate directly
> on derived-class references. To me, that seems unusual.

If you think about the Visitor DP, it is quite usual indeed.
(provided the Visitor is usual, I personnaly find it overused
but that's another issue).
Actually, I do not see a lot of complex task performed on a
object for which a part of that task doesn't know more than
the root (what I see is some virtual call learning the type
and then some work being done).

> We're talking about adding a keyword which will turn a
> virtual call into a direct one,

Or into an inlined call. As for the cost of a virtual call
vs a direct call, that is something that could be discussed.
I have seen a some amount of effort invested by knowledgable
people that was assuming it wasn't that low (which is not a proof).

> at call sites which receive
> a pointer or reference to a derived class instead of to a
> base class. Since such an optimization is useful only when
> the call does nothing or nearly nothing,

Many functions do nearly nothing.

> it seems like such
> a remote circumstance that there's no worth in doing it.

Migh be true, or not :-)

Alain

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Thu, 19 Dec 2002 00:38:44 +0000 (UTC)
Raw View
Fergus Henderson wrote:
>
> petebecker@acm.org (Pete Becker) writes:
>
> >Fergus Henderson wrote:
> >>
> >> Class hierarchy browsers generally don't catch template classes for which
> >> there are no instantiations.  Also, they require that the program be
> >> in a compilable state, which is often not the case during maintenance.
> >
> >In which case final won't help you, either.
>
> Final *will* help here, because I can just add "final", and continue
> on with the rest of my programming task. I can be confident that my
> invariants won't be broken.

Danger, danger, context switch. The original assertion was that

>> If the Array class is used in
>> a large number of places, it may be difficult to determine whether there
>> is any code which derives from Array.
>

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Thu, 19 Dec 2002 00:38:58 +0000 (UTC)
Raw View
Allan W wrote:
>
> Come on, Pete. You must see this too -- and with over 250 messages in
> this thread, surely I'm not the first to point this out.
>

Actually, you are the first to mention it. I'm well aware of it, but I'm
not convinced that final is the only way to do this.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: allan_w@my-dejanews.com (Allan W)
Date: Thu, 19 Dec 2002 04:07:32 +0000 (UTC)
Raw View
petebecker@acm.org (Pete Becker) wrote
> If it's useful in Java that proves it is useful in Java. Transferring
> that knowledge from Java to C++ requires a far more detailed analysis.
> It requires understanding what it does in Java and why that's
> beneficial, then determining whether the same issues are present in C++
> and whether it would provide the same benefits.

Agreed.

But, since "final" is implemented in Java, doesn't the analysis for what
it should do in C++ start with an analysis of what it already does there?

Shouldn't this analysis continue in public debates such as this one?

In short, aren't you currently part of the very process you're complaining
hasn't been done?

You seem to be saying that we shouldn't do it because it hasn't been
analyzed, and that we shouldn't analyze it because we don't do that.
I'm sure I've oversimplified your position...

---
[ 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: allan_w@my-dejanews.com (Allan W)
Date: Thu, 19 Dec 2002 04:07:57 +0000 (UTC)
Raw View
> Allan W wrote:
> > Please perform some simple statistics
> > and report back -- while the performance difference does exist, I
> > think you might be surprised just how minor they are.

alain@miniussi.net (Alain Miniussi) wrote
> They can be minor or big depending on how you fake the benchmark,

"Fake the benchmark?" Perhaps this is a literal English-language
translation of a non-English idiom. Taken literally, it means you're
lying -- which I'm certain you don't mean to say. (Even if it was
true, you wouldn't say so -- and I have no reason to think you are
lying.)

> (by the way, I did it, and was surprised of how big the difference
> can be, thanks :).

This surprised you? Your numbers:

> ** NONE ** vcall> time ./a.out
> real    0m4.434s
> user    0m4.390s
> sys     0m0.010s
> ** NONE ** vcall> time ./a.out not virtual
>
> real    0m0.028s
> user    0m0.030s
> sys     0m0.000s
> ** NONE ** vcall>

This difference is greater than I expected, but...

> But then, who wants to return 42 100000000 times....

I think this means that you called a function 100 million times,
which simply returned the number 42? Something like:

    struct Foo {
    #ifdef VIRTUAL
        virtual
    #endif
        int foo();
    };
    int Foo:foo() { return 42; }

    int main() {
        Foo f;
        for (long i=0; i<100000000L; ++i) f.foo();
    }

If this is comparable to your test harness, then it makes my point.
Calling a virtual function 100 million times caused the program to
run 4.406 seconds slower; in other words, each virtual function call
took an additional 44.06 nanoseconds over a comparable non-virtual
call. Surely this would have no measurable impact on real programs.

---
[ 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: pdimov@mmltd.net (Peter Dimov)
Date: Thu, 19 Dec 2002 04:08:08 +0000 (UTC)
Raw View
kanze@gabi-soft.de (James Kanze) wrote in message news:<d6651fb6.0212180148.5696fb2e@posting.google.com>...
> allan_w@my-dejanews.com (Allan W) wrote in message
> news:<7f2735a5.0212171519.6ae4ff42@posting.google.com>...
> > pdimov@mmltd.net (Peter Dimov) wrote in message
> > news:<7dc3b1ea.0212170733.7d08ef9b@posting.google.com>...
> > > allan_w@my-dejanews.com (Allan W) wrote in message
> > > news:<7f2735a5.0212161806.1e64e9de@posting.google.com>...
>
>     [...]
> > > shared_ptr<shape> create_circle();
> > > shared_ptr<shape> create_rectangle();
> > > shared_ptr<shape> create_other();

[...]

>   - He effectively prevents the derived class from offering an extended
>     interface.  What happens if I want to offer some special additional
>     functionality in circle, for the case where the user knows he has a
>     circle?

You offer an abstract circle, of course, that provides a
circle-specific interface, and return a shared_ptr<circle>.

[...]

> The idiom is useful in some cases.  It is probably appropriate in this
> particular case.  But it isn't appropriate everywhere, and it isn't a
> general answer to the problem.

Well, this is textbook implementation hiding that happens to block
derivation as a side effect, with the associated pros (no
recompilation of client) and cons (indirection). I mostly agree with
your objections, but the idiom is quite useful in _many_ cases, not
just _some_ cases. :-)

---
[ 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: usenet@phatbasset.com ("Hillel Y. Sims")
Date: Thu, 19 Dec 2002 05:16:01 +0000 (UTC)
Raw View
"Hyman Rosen" <hyrosen@mail.com> wrote in message
news:1040228046.101830@master.nyc.kbcfp.com...
> What we objectors are saying is that just because a
> buggy whip makes a horse-drawn cart go faster, that
> doesn't mean that automobiles should come equipped
> with one.

If C++ is like an automobile, how about a keyword 'turbo' that makes
everything it is applied to go faster?

hys

--
(c) 2002 Hillel Y. Sims
FactSet Research Systems
hsims AT factset.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: scottm@toast.net ("Scott Mayo")
Date: Thu, 19 Dec 2002 05:16:30 +0000 (UTC)
Raw View
"Alain Miniussi" <alain@miniussi.net> wrote in message
news:v0226hrbfadec4@corp.supernews.com...

> I would be personally more than reluctant in using
> final for optimisation purpose.

It depends. If you are writing a library, and the absolute
maximum performance possible was a non-goal,
you'd avoid it. If you are writing a black-box application,
and performance is everything, you'd consider it
strongly. As someone who dabbles in game programming,
and has seen situations where optimizing out individual
machine instructions made a difference, I can tell you
that the some people write such things. Aggressive
use of const, inline, register and perhaps private can
get you very measurable performance improvements.
So can removing virtual functions, at the cost of code
clarity. 'final' offers a way to keep the convenience of
virtual functions - and that's all virtual functions are, a
notational convenience - without paying a performance
cost. For most situations, the performance cost is
completely negligable. For a few, it absolutely is not.

I see other potential optimizations based on final. For
most people they are, again, irrelevant. (For many people,
it's not worth turning on a compiler's optimizer at all:
machines are fast, and why risk an optimizer bug if you
don't need the speed?) But a really clever compiler
could consider repacking or even (gasp) *rearranging*
the variables of a final class in a non-standard way, if
doing so would cause the class to fit within the CPUs
cache segment size. (Avoiding cache misses can help
performance greatly.) You can't even consider this
approach if someone might derive from your class.
And a compiler can get very aggressive about inlining,
and hence register allocation, when it knows it has the
absolute last word on how functions are called.

Now, I *know* what follows is biased to my point of view, thank
you, but as far as I can tell, this is what we have so far:

Pros of class-wide final:
1. final can preserve the intent of the class provider, which is
of some benefit when it is known that the class is inherently
fragile when extended (or just when the author would be
on the hook for answering service calls when people
try to extend his code, mess it up, and blame the author -
not an uncommon situation for businesses.)

2. final can provide for certain optimizations, which is irrelevant
for many but important to a few.

3. final has not been observed to bring about the end of all
extensibility in Java - even though it is every bit as restrictive as
the variant proposed for C++ - so there is some anecdotal
evidence that it won't destroy C++ either. It has the same
*effect* in Java and C++ - halting further extension - and
hence qualifies as valid prior art for the concept.

Cons:
1. Someone might misuse it and prevent you from extending his
classes; how dare they write code and then limit how you use it!

It seems to me that capitalism takes care of that con. If someone
marks his classes as final and you don't like that, don't buy them.
Someone else will sell you a non-final equivalent in short order.
The marketplace will sort this out automatically.




---
[ 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: kanze@gabi-soft.de (James Kanze)
Date: Thu, 19 Dec 2002 15:39:12 +0000 (UTC)
Raw View
pdimov@mmltd.net (Peter Dimov) wrote in message
news:<7dc3b1ea.0212181543.128cdbd7@posting.google.com>...
> kanze@gabi-soft.de (James Kanze) wrote in message
> news:<d6651fb6.0212180148.5696fb2e@posting.google.com>...
> > allan_w@my-dejanews.com (Allan W) wrote in message
> > news:<7f2735a5.0212171519.6ae4ff42@posting.google.com>...
> > > pdimov@mmltd.net (Peter Dimov) wrote in message
> > > news:<7dc3b1ea.0212170733.7d08ef9b@posting.google.com>...
> > > > allan_w@my-dejanews.com (Allan W) wrote in message
> > > > news:<7f2735a5.0212161806.1e64e9de@posting.google.com>...

> >     [...]
> > > > shared_ptr<shape> create_circle();
> > > > shared_ptr<shape> create_rectangle();
> > > > shared_ptr<shape> create_other();

> [...]

> >   - He effectively prevents the derived class from offering an
> >     extended interface. What happens if I want to offer some special
> >     additional functionality in circle, for the case where the user
> >     knows he has a circle?

> You offer an abstract circle, of course, that provides a
> circle-specific interface, and return a shared_ptr<circle>.

Good suggestion.  If it works for the base interface, it works for the
derived interface.  And of course, shared_ptr< circle > converts
implicitly into shared_ptr< shape >, and dynamic_cast< shared_ptr<
circle > > works as expected given a shared_ptr< shape >.

(The last remark, of course, has nothing to do with the discussion at
hand, but should be taken as a very strong hint that a name for this
operation should be standardized, so that what works with your
shared_ptr works with my (invasive) RefCntPtr, etc.)

> [...]

> > The idiom is useful in some cases. It is probably appropriate in
> > this particular case. But it isn't appropriate everywhere, and it
> > isn't a general answer to the problem.

> Well, this is textbook implementation hiding that happens to block
> derivation as a side effect, with the associated pros (no
> recompilation of client) and cons (indirection). I mostly agree with
> your objections, but the idiom is quite useful in _many_ cases, not
> just _some_ cases. :-)

Just to be clear: I like the idiom, and I use it a lot.  My "some" was
meant in the most general sense, more than zero, and less than all.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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: kanze@gabi-soft.de (James Kanze)
Date: Thu, 19 Dec 2002 15:39:23 +0000 (UTC)
Raw View
hyrosen@mail.com (Hyman Rosen) wrote in message
news:<1040226478.583165@master.nyc.kbcfp.com>...
> Scott Mayo wrote:
> > I dislike Java too, but I'm not willing to dismiss an entire
> > language out of hand. It turns out that Java has a structure roughly
> > similar to C++ in terms of classes, and 'final' has the same
> > semantics as it would in C++. 'final' solves a problem in Java (even
> > if you don't agree that there is such a problem)

> This has nothing to do with liking or disliking Java.  While the class
> structure of C++ and Java are roughly similar, 'final' solves a
> problem for Java that exists only in Java, at a place where the
> differences in class structure show up.  We don't agree that there is
> an equivalent problem in C++, and therefore the presence of 'final' in
> Java is not (useful) prior art for C++.

You don't agree that ensuring class invariants is a problem for C++
code?  (You can, of course, solve it at runtime in C++, which you cannot
do in Java if the base class is an interface.  On the other hand,
solving it at run time can be quite expensive in run-time, and when a
simple, compile time solution exists...)

> The problem for Java is that it has no object types, only pointers to
> objects, and no non-virtual functions.  Therefore, to gain some of the
> advantages of inline and direct function calls, that language needs a
> way to bypass the virtual mechanism. In C++, you can just make methods
> non-virtual.

So what does that have to do with final?  Java compilers do, in fact,
inline functions and generate direct function calls, according to the
use of the function.  And independantly of whether the function is final
or not.

The optimization issue is a red herring.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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: kanze@gabi-soft.de (James Kanze)
Date: Thu, 19 Dec 2002 15:39:33 +0000 (UTC)
Raw View
hyrosen@mail.com (Hyman Rosen) wrote in message
news:<1040246143.60616@master.nyc.kbcfp.com>...
> Francis Glassborow wrote:
> > Once we have started we cannot stop.

> Correct, and the question becomes whether the ability to stop is
> important enough to warrant the inclusion of final into C++, given
> that many of us think that it will be more misused than used
> appropriately.

You mean like operator overloading?

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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: kanze@gabi-soft.de (James Kanze)
Date: Thu, 19 Dec 2002 15:41:25 +0000 (UTC)
Raw View
alain@miniussi.net (Alain Miniussi) wrote in message
news:<v01n4qjmtett48@corp.supernews.com>...
> James Kanze wrote:
> > scottm@toast.net ("Scott Mayo") wrote in message
> > news:<3dfcdb0d@news.toast.net>...
> >> and it would allow possible optimizations of the code.

> > Optimizations which a (very) good optimizer could find anyway.

> Not a very strong argument, IMO. Inlining of non virtual function is a
> lot easier then inlining of virtual functions. easier to the point
> that the former is done in practice, not the later.

Come now.  In principal, there is no difference, if you know which
function is actually being called.  I seem to remember one person
explaining to me how it worked, at a former employer of yours, no less.

What is certain is that not all compilers are at this level yet.  On the
other hand, the motivation to get them there should exist, since Sun's
HotSpot compiler for Java does this (and we can't have Java beating C++
in speed, can we?).

> Even considering cross module inlining. With the same argument, you
> don't need "inline" (I am not saying we'd get as much benefit as with
> inline, I am just questioning the argument).

> Of course, "with tomorow's compilers..."

With some of today's compilers.  David Vandervoorde sent me an article
at least four years ago which described such a compiler.  For years ago
isn't tomorrow.  If such compilers aren't widespread, it is simply
because there is no demand for them.  Partially, of course, because most
applications don't need that sort of optimization.  But also because a
number of companies seem to think it cheaper to spend man-years of
effort hand tuning code rather than to pay, say $5000 a seat more for a
compiler.

> >> It might be used to indicate that the class is not written in a way
> >> that makes general derivation safe; it might indicate that this is
> >> my code not your code, and I don't want you extending it because
> >> you haven't arranged for that right with me, or it might see use
> >> when every possible optimization is needed.  The latter is the main
> >> justification for it in Java.

> > I don't think I've ever seen final used for optimization in Java.
> > The most frequent use at the class level is simply to document that
> > the class really should have value semantics, but since Java doesn't
> > support this...  There is a proposal (from Gosling) concerning
> > optimization, but it involves a new keyword (immutable, I think):
> > not only must the class be final, but it must have no mutating
> > (non-const in C++ speak) functions.

> >> I don't know of a hue and cry against 'final' in Java, though I
> >> suppose opponents could claim this is because final is so necessary
> >> (Java performs hideously without it) that it has ceased to be seen
> >> as evil.

> > Java performs very well, thank you.  I've seen benchmarks where it
> > beats C++.  Without using final.

> For non numeric applications ?

Only for applications which made extensive use of arrays (of basic
types).  Not necessarily numeric, but not necessarily typical of all
applications either.

> I remember final making a difference in Java, it was a few years back

I can remember when final would have made a difference, too.  But as you
say, it was a few years back.  It doesn't seem to affect HotSpot.

> (anyway, I have seen benchmarks showing purely symbolic languages
> being faster than C, and I have seen how people did the benchmarks for
> Java perf, those people cannot be trusted :-).

Never trust a benchmark you haven't falsified yourself:-).  I did a
benchmark which showed Java and g++ for Windows at about the same
performance levels when I was at the Dresdner Bank.

In the end, if final has some performance benefits, so much the better.
But that certainly isn't the main reason for proposing it.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Thu, 19 Dec 2002 16:03:30 +0000 (UTC)
Raw View
James Kanze wrote:
>
> hyrosen@mail.com (Hyman Rosen) wrote in message
> news:<1040226478.583165@master.nyc.kbcfp.com>...
> > Scott Mayo wrote:
> > > I dislike Java too, but I'm not willing to dismiss an entire
> > > language out of hand. It turns out that Java has a structure roughly
> > > similar to C++ in terms of classes, and 'final' has the same
> > > semantics as it would in C++. 'final' solves a problem in Java (even
> > > if you don't agree that there is such a problem)
>
> > This has nothing to do with liking or disliking Java.  While the class
> > structure of C++ and Java are roughly similar, 'final' solves a
> > problem for Java that exists only in Java, at a place where the
> > differences in class structure show up.  We don't agree that there is
> > an equivalent problem in C++, and therefore the presence of 'final' in
> > Java is not (useful) prior art for C++.
>
> You don't agree that ensuring class invariants is a problem for C++
> code?

Of course everyone agreees with that. The real issue in this area is
what does final contribute to solving this problem.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: Thu, 19 Dec 2002 17:40:43 +0000 (UTC)
Raw View
hyrosen@mail.com (Hyman Rosen) writes:

>Since such an optimization is useful only when
>the call does nothing or nearly nothing, it seems like such
>a remote circumstance that there's no worth in doing it.

What makes you think that it is rare for the body of a virtual
function to do little?

--
Fergus Henderson <fjh@cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.

---
[ 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: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: Thu, 19 Dec 2002 17:42:46 +0000 (UTC)
Raw View
petebecker@acm.org (Pete Becker) writes:

>Fergus Henderson wrote:
>>
>> petebecker@acm.org (Pete Becker) writes:
>>
>> >Fergus Henderson wrote:
>> >>
>> >> Class hierarchy browsers generally don't catch template classes for which
>> >> there are no instantiations.  Also, they require that the program be
>> >> in a compilable state, which is often not the case during maintenance.
>> >
>> >In which case final won't help you, either.
>>
>> Final *will* help here, because I can just add "final", and continue
>> on with the rest of my programming task. I can be confident that my
>> invariants won't be broken.
>
>Danger, danger, context switch. The original assertion was that
>
>>> If the Array class is used in
>>> a large number of places, it may be difficult to determine whether there
>>> is any code which derives from Array.

This was in the context of adding a new member function such as swap()
to the Array class.  `final' will help in that situation.  Adding
final and recompiling won't immediately tell us if there is any code
which derives from Array, because it won't catch cases which occur in
uninstantiated templates.  But adding final provides a guarantee that
you'll get a compile error if/when any such templates do get instantiated.
And that's all you really need.  If it turns out that there are some such
occurrences, you can if need be reconsider the design decision to add
a swap() member to the Array class.

Without `final', you're stuck in the situation where adding a new member
function like swap() is error-prone and there's no easy way to detect
all the places which might end up invoking swap() in a way that violates
its preconditions.

--
Fergus Henderson <fjh@cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.

---
[ 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, 19 Dec 2002 17:44:28 +0000 (UTC)
Raw View
Francis Glassborow wrote:
> The adjective 'arrogant' has been used in this thread, I might add
> 'paternalistic'. Could we stick to the technical merits of a proposal.

We are debating a feature that will enable programmers to be
arrogant and paternalistic.

---
[ 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, 19 Dec 2002 17:44:43 +0000 (UTC)
Raw View
Dan'l Miller wrote:
>   Since I explicitly posited it as a given in the design scenario which
> I was discussing.  I left no wiggle room in this regard.  Please color
> within the lines.

Since a derived overrider can just call the function it's overriding,
it's always possible to override without breaking invariants. So you
are setting up a strawman.

---
[ 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: kanze@gabi-soft.de (James Kanze)
Date: Thu, 19 Dec 2002 17:48:32 +0000 (UTC)
Raw View
scottm@toast.net ("Scott Mayo") wrote in message
news:<3e01527c@news.toast.net>...

> Now, I *know* what follows is biased to my point of view, thank you,
> but as far as I can tell, this is what we have so far:

I'm in favor of final too, at least for functions.  But let's try and be
fair.

> Pros of class-wide final:
> 1. final can preserve the intent of the class provider, which is
> of some benefit when it is known that the class is inherently
> fragile when extended (or just when the author would be
> on the hook for answering service calls when people
> try to extend his code, mess it up, and blame the author -
> not an uncommon situation for businesses.)

This is also true for a function level final.

> 2. final can provide for certain optimizations, which is irrelevant
> for many but important to a few.

For the most part, I think that this is also true for a function level
final.

> 3. final has not been observed to bring about the end of all
> extensibility in Java - even though it is every bit as restrictive as
> the variant proposed for C++ - so there is some anecdotal evidence
> that it won't destroy C++ either. It has the same *effect* in Java and
> C++ - halting further extension - and hence qualifies as valid prior
> art for the concept.

The examples of where final might cause problems cited by Dave and Peter
all involved templates, I believe.  Which makes the fact that no one has
noticed them in Java rather a pleonasm.

On the other hand, I don't think that the problems they mentioned affect
a function level final.

> Cons:
> 1. Someone might misuse it and prevent you from extending his classes;
> how dare they write code and then limit how you use it!

The main concrete con that I have heard mentionned was the limitations
with regards to some fancy metaprogramming techniques.  The fact that
something can be misused has never been an obstacle to incorporating it
into C++ (although the fact has been mentionned).

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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: kanze@gabi-soft.de (James Kanze)
Date: Thu, 19 Dec 2002 17:48:44 +0000 (UTC)
Raw View
alain@miniussi.net (Alain Miniussi) wrote in message
news:<v0226hrbfadec4@corp.supernews.com>...
> Hyman Rosen wrote:

> > Alain Miniussi wrote:
> >> This looks like the argument usually made for inline

> > I expect James Kanze can tell you what he considers best practice
> > with respect to that :-) I doubt that it includes willy-nilly
> > inlining of everything.

> I remember reading that his principles were relaxed when it came to
> one liner where the inlined code would be shorter than the call.

You read wrong.  Or you read something I wrote some years back.

The more I use C++, the less I make inline.  My current policy is to
make nothing (and I mean absolutely nothing) inline, however, so I doubt
that this trend will continue.

It's important to point out, however, that I work on application code.
I have access to the final program, I can see what its performance is,
and I can make any modifications I want to correct a real performance
problem.  I have some understanding that library providers don't have
that luxury.  Someone writing an implementation of the standard library
can probably consider that std::vector<>::operator[] will be in a
critical path in some application, somewhere, even if he doesn't have
immediate profiling data to back it up.

What this has to do with final, however, I don't know.  I can't remember
ever seeing a performance problem due to virtual function calls, when
the function should have been virtual in the base class.  (Obviously, if
you declare the operator[] in vector virtual...)  And there is a simple
solution (which I regularly used in my pre-standard array classes):

    template< typename T >
    class AbstractArray
    {
    public:
        T&                  operator[]( int index )
        {
            return doIndex( index ) ;
        }

    private:
        virtual T&          doIndex( int index ) = 0 ;
    } ;

    template< typename T >
    class ConcreteArray
    {
    public:
        T&                  operator[]( int index )
        {
            //  The real implementation...
        }

    private:
        virtual T&          doIndex( int index )
        {
            return operator[]( index ) ;
        }
    } ;

When I need the virtual dispatch, the function takes an AbstractArray&.
When I need the speed, and I know that the actual type will be
ConcreteArray, the function takes a ConcreteArray&.  (And in my case,
the operator[] in ConcreteArray was inline.  But of course, the code was
written some time ago:-).)

I forget who I originally plagerized for this idea, but it isn't new;
I've been doing it for at least ten years.

I repeat: the optimization issue is a red herring with regards to final.
The real issue is whether you think the author of a class should be in
charge of his class invariants, or whether you think that anyone who
might want to derive from the class should be permitted to violate the
invariants arbitrarily.  Put that way, it sounds like the answer is
obvious.  To me it is, but surprisingly, I've run into not a few people
who insist that all functions should be virtual.  Always.  Still, in
C++, I think the general trend is to recognize that at least some
functions shouldn't be redefinable.  Not for optimization reasons, but
because we want to be able to write correct code.  This is, after all,
one of the motivations (mine, at least) behind forbidding public
functions to be virtual in many cases.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Thu, 19 Dec 2002 17:50:46 +0000 (UTC)
Raw View
Allan W wrote:
>
> petebecker@acm.org (Pete Becker) wrote
> > If it's useful in Java that proves it is useful in Java. Transferring
> > that knowledge from Java to C++ requires a far more detailed analysis.
> > It requires understanding what it does in Java and why that's
> > beneficial, then determining whether the same issues are present in C++
> > and whether it would provide the same benefits.
>
> Agreed.
>
> But, since "final" is implemented in Java, doesn't the analysis for what
> it should do in C++ start with an analysis of what it already does there?
>

It could. I haven't seen anyone do this.

> Shouldn't this analysis continue in public debates such as this one?
>

Sure, if someone does it. The problem is that people present the outline
for a discussion as if it were complete and conclusive. And oddly
enough, these demonstrations always ending up supporting the position of
the person who presents them.

> In short, aren't you currently part of the very process you're complaining
> hasn't been done?
>
> You seem to be saying that we shouldn't do it because it hasn't been
> analyzed, and that we shouldn't analyze it because we don't do that.
> I'm sure I've oversimplified your position...
>

You sure have. My position is that we shouldn't change the language
until someone demonstrates a need, supported by analysis that's detailed
enough to show an understanding of the underlying issues.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: scottm@toast.net ("Scott Mayo")
Date: Thu, 19 Dec 2002 17:51:42 +0000 (UTC)
Raw View
"Allan W" <allan_w@my-dejanews.com> wrote in message
news:7f2735a5.0212181531.22d7b4b6@posting.google.com...

> Calling a virtual function 100 million times caused the program to
> run 4.406 seconds slower; in other words, each virtual function call
> took an additional 44.06 nanoseconds over a comparable non-virtual
> call. Surely this would have no measurable impact on real programs.

It can. 44 nanoseconds is measurable when you have a few hundred
thousand operations to get though and you are racing against a piece
of video hardware that refreshes many times a second. And his test
probably didn't provoke cache misses. If the processor had stalled
on the additional memory fetch each time...

I don't suppose many people deal with speed anymore; if you are
crunching financials, spitting up some HTML or doing a database
insert, it rarely matters if the processor runs at 200Mhz or 2000Mhz.
And that's probably what most programming is these days.

For grins - and this is not any sort of product endorsement, this is
purely an example - read this writup on how to optimize
code for one particular AMD processor:
    http://www.amd.com/products/cpg/athlon/techdocs/pdf/22007.pdf
When you get to the part that shows how to make a loop
(that sums the elements of two arrays) run faster, and the change turns out
to *add* dozens of additional memory references to the code but yield a
50% improvement in speed, you may begin to appreciate the joys
of optimization - and why writing really efficient code can be more
than a little challanging. It's always nice when we can coerce a
compiler to do a better job. A lot nicer than having to fall back on
obscure coding tricks (*look* at the things that techdoc proposes,
to get at the real speed of the hardware!) or assembler.




---
[ 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: alain@miniussi.net (Alain Miniussi)
Date: Thu, 19 Dec 2002 17:53:10 +0000 (UTC)
Raw View
Allan W wrote:

>> Allan W wrote:
>> > Please perform some simple statistics
>> > and report back -- while the performance difference does exist, I
>> > think you might be surprised just how minor they are.
>
> alain@miniussi.net (Alain Miniussi) wrote
>> They can be minor or big depending on how you fake the benchmark,
>
> "Fake the benchmark?" Perhaps this is a literal English-language
> translation of a non-English idiom. Taken literally, it means you're
> lying -- which I'm certain you don't mean to say.

It's not a lie, but it is certainly a fraud: it is possible to
produce benchmarks showing it matter, others showing it does not.
I picked up one that does, it can be invalidated and I did not
point it out.

> (Even if it was true, you wouldn't say so --

Yes, I would, I am an *honest* liar.

> and I have no reason to think you are
> lying.)

Thank you I apreciate that.

>> (by the way, I did it, and was surprised of how big the difference
>> can be, thanks :).
>
> This surprised you? Your numbers:
>
>> ** NONE ** vcall> time ./a.out
>> real    0m4.434s
>> user    0m4.390s
>> sys     0m0.010s
>> ** NONE ** vcall> time ./a.out not virtual
>>
>> real    0m0.028s
>> user    0m0.030s
>> sys     0m0.000s
>> ** NONE ** vcall>
>
> This difference is greater than I expected, but...
>
>> But then, who wants to return 42 100000000 times....
>
> I think this means that you called a function 100 million times,
> which simply returned the number 42? Something like:
>
>     struct Foo {
>     #ifdef VIRTUAL
>         virtual
>     #endif
>         int foo();
>     };
>     int Foo:foo() { return 42; }
>
>     int main() {
>         Foo f;
>         for (long i=0; i<100000000L; ++i) f.foo();
>     }
>
> If this is comparable to your test harness,

It is not, it has 2 classes, also, no two consecutive calls
were made through the same object, the real type wasn't
known at call site (I expect to see no difference in your
code since the compiler has no reason to do that call through
the virtual table).

On the other hand, there was only one virtual function and
one vtable, which probably improve things, the example is
so small that locality is not an issue, the result of the function
is not used in the exact way that would make the virtual call look
bad etc....

So both our examples are not a good approximation of
real life (which is why I said it was a lie/fraud).

> then it makes my point.

The non virtual call was inlined, I suspect (through cross module
inlining, I purposely choose a compiler implementing that, (I'm telling
you, I can't be trusted :-)) so whatever point you make against it
is probably a valid argument against inline (which is accepted).

> Calling a virtual function 100 million times caused the program to
> run 4.406 seconds slower;

(Side note: Similar conclusion can be drawn by considering a program
calling the function against a program doing *nothing*).

Or you can look at how many slower it is, and put that code in
whatever bottelneck you find in the application and wonder how
we can live whitout that.

Or not.

Tools have been developped to eliminate virtual calls, so I guess
in some cases it does matter (I don't think my numbers proves
it, as I don't think your analyzis disproves it).

Investing the required effort on a realistic example would impact
my guitar practice which is something I refuse to do. But some people
did (for a possibly invalid exemple:
http://www.cs.ucsb.edu/labs/oocsb/papers/ecoop96.pdf, I guess there
are others)

Regards,

Alain

PS: again, I don't really care about final, the perf aspect probably
won't apply to my code and have been able to survive whithout the
soft. eng. aspect so far. But if other people do care, I am sure
they can come with valid argument and I don't see a lot of arguments
to put in front of that excepted for the problems related to final
becoming a reserved word and the feature being missused.

> in other words, each virtual function call
> took an additional 44.06 nanoseconds over a comparable non-virtual
> call. Surely this would have no measurable impact on real programs.

No problem, I can multiply that number :-)


---
[ 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: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Thu, 19 Dec 2002 18:56:35 +0000 (UTC)
Raw View
kanze@gabi-soft.de (James Kanze) writes:

[...]

| You don't agree that ensuring class invariants is a problem for C++
| code?

I didn't see anyone disputing that; did you?

I believe that one of the key issues is about the real (not supposed)
contribution of "final" in solving that problem.

--
Gabriel Dos Reis,       gdr@integrable-solutions.net

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Thu, 19 Dec 2002 18:56:41 +0000 (UTC)
Raw View
Fergus Henderson wrote:
>
> petebecker@acm.org (Pete Becker) writes:
>
> >Fergus Henderson wrote:
> >>
> >> petebecker@acm.org (Pete Becker) writes:
> >>
> >> >Fergus Henderson wrote:
> >> >>
> >> >> Class hierarchy browsers generally don't catch template classes for which
> >> >> there are no instantiations.  Also, they require that the program be
> >> >> in a compilable state, which is often not the case during maintenance.
> >> >
> >> >In which case final won't help you, either.
> >>
> >> Final *will* help here, because I can just add "final", and continue
> >> on with the rest of my programming task. I can be confident that my
> >> invariants won't be broken.
> >
> >Danger, danger, context switch. The original assertion was that
> >
> >>> If the Array class is used in
> >>> a large number of places, it may be difficult to determine whether there
> >>> is any code which derives from Array.
>
> This was in the context of adding a new member function such as swap()
> to the Array class.  `final' will help in that situation.  Adding
> final and recompiling won't immediately tell us if there is any code
> which derives from Array,

Recompiling certainly won't help if the program is not in a compilable
state, which is the reason you gave for not being able to use a browser.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: alain@miniussi.net (Alain Miniussi)
Date: Thu, 19 Dec 2002 18:57:07 +0000 (UTC)
Raw View
James Kanze wrote:

> alain@miniussi.net (Alain Miniussi) wrote in message
> news:<v0226hrbfadec4@corp.supernews.com>...
>> Hyman Rosen wrote:
>
>> > Alain Miniussi wrote:
>> >> This looks like the argument usually made for inline
>
>> > I expect James Kanze can tell you what he considers best practice
>> > with respect to that :-) I doubt that it includes willy-nilly
>> > inlining of everything.
>
>> I remember reading that his principles were relaxed when it came to
>> one liner where the inlined code would be shorter than the call.
>
> You read wrong.

I would says that's unlikely, I remember it struck me comming
from you :-)

> Or you read something I wrote some years back.

That's likely.

> The more I use C++, the less I make inline.  My current policy is to
> make nothing (and I mean absolutely nothing) inline, however, so I doubt
> that this trend will continue.

[..]
> What this has to do with final, however, I don't know.  I can't remember
> ever seeing a performance problem due to virtual function calls, when
> the function should have been virtual in the base class.

But others did, if final can helps them, what argument can be opposed ?

>  (Obviously, if
> you declare the operator[] in vector virtual...)  And there is a simple
> solution

But it can be miss-used (ok, that's unfair) :-)
Now, wouldn't final simplify that solution ? (and
maybe make it safer by preventing
ReallyConcreteConcreteArray from overriding doIndex ?).

> (which I regularly used in my pre-standard array classes):
>
>     template< typename T >
>     class AbstractArray
>     {
>     public:
>         T&                  operator[]( int index )
>         {
>             return doIndex( index ) ;
>         }
>
>     private:
>         virtual T&          doIndex( int index ) = 0 ;
>     } ;
>
>     template< typename T >
>     class ConcreteArray

Did you forgot a derivation ?

>     {
>     public:
>         T&                  operator[]( int index )
>         {
>             //  The real implementation...
>         }
>
>     private:
>         virtual T&          doIndex( int index )
>         {
>             return operator[]( index ) ;
>         }
>     } ;

[..]

> I repeat: the optimization issue is a red herring with regards to final.
> The real issue is whether you think the author of a class should be in
> charge of his class invariants, or whether you think that anyone who
> might want to derive from the class should be permitted to violate the
> invariants arbitrarily.  Put that way, it sounds like the answer is
> obvious.  To me it is, but surprisingly, I've run into not a few people
> who insist that all functions should be virtual.  Always.  Still, in
> C++, I think the general trend is to recognize that at least some
> functions shouldn't be redefinable.  Not for optimization reasons, but
> because we want to be able to write correct code.  This is, after all,
> one of the motivations (mine, at least) behind forbidding public
> functions to be virtual in many cases.

This is one (valid) tactique, but these are not everybody's choices (of
course, establish which one is more common really depends on the
sample you choose).

Regards,

Alain

---
[ 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: pdimov@mmltd.net (Peter Dimov)
Date: Thu, 19 Dec 2002 19:41:34 +0000 (UTC)
Raw View
fjh@students.cs.mu.OZ.AU (Fergus Henderson) wrote in message news:<atqfcj$7tu$1@mulga.cs.mu.OZ.AU>...
> pdimov@mmltd.net (Peter Dimov) writes:
[...]
>  >"swap" will correctly swap the values of the two objects. The fact
>  >that it the argument is a subobject, and not a complete object, is of
>  >no concern to "swap" itself.
>
> "The two objects" referred to in my definition above of what semantics
> I intended for swap are the most derived objects referred to by
> the parameters, not the base class sub-objects corresponding to the
> parameters' static types.  If I had intended swap() to just swap the
> base class sub-objects, I would have named it swap_subobjects().
>
> Note that I wrote that code, so I get to define the intended semantics!

Most definitely. ;-) Now consider:

class X
{
  int a;

public:

  void swap(X & x) { std::swap(a, x.a); }
};

class Y: public X
{
  int b;

public:

  void swap(Y & y) { X::swap(y); std::swap(b, y.b); }
};

Note how X::swap is "abused" by Y::swap, since neither *this nor y
have dynamic type X, and yet, somehow, Y::swap is correct. This leads
me to think that your X::swap preconditions are overly restrictive.

[...]

> The use of inheritence in this context means that swap()'s preconditions
> can easily be accidentally violated due to this implicit conversion.
> So I do put some of the blame for such failures on the derivation.
> But I agree that inheritence alone is not *solely* responsible.

Esp. since private inheritance doesn't have this problem.

>  >Many derived classes don't break in such situations. The
>  >derived class may have no state, or it may have state that is
>  >independent of the state of the base class.
>
> Having no (extra) state is OK.  In that case the call to swap()
> won't break anything.
>
> But if the derived class has state which is independent of the base class
> state, then it's still broken, at least semantically, since the call
> to swap() does not have the effect intended by the author of swap().
> The caller of swap() is relying on implementation details of swap()
> rather than the semantics that was intended, implied (IMHO) by its name,
> and documented above.  Now, it may happen that the code "works", but
> it's still broken.

Not necessarily. If the extra state is not "value-based" but
"identity-based" (a reference count, a weak pointer to this), it
should not be swapped.

---
[ 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: alain@miniussi.net (Alain Miniussi)
Date: Thu, 19 Dec 2002 19:42:00 +0000 (UTC)
Raw View
James Kanze wrote:

> alain@miniussi.net (Alain Miniussi) wrote in message
> news:<v01n4qjmtett48@corp.supernews.com>...
>> James Kanze wrote:
>> > scottm@toast.net ("Scott Mayo") wrote in message
>> > news:<3dfcdb0d@news.toast.net>...
>> >> and it would allow possible optimizations of the code.
>
>> > Optimizations which a (very) good optimizer could find anyway.
>
>> Not a very strong argument, IMO. Inlining of non virtual function is a
>> lot easier then inlining of virtual functions. easier to the point
>> that the former is done in practice, not the later.
>
> Come now.  In principal, there is no difference, if you know which
> function is actually being called.  I seem to remember one person
> explaining to me how it worked, at a former employer of yours, no less.

Maybe you overlooked some part of the explanation, I didn't say one
was possible and the other was impossible, I said "easier to the point
that...".

> What is certain is that not all compilers are at this level yet.  On the
> other hand, the motivation to get them there should exist, since Sun's
> HotSpot compiler for Java does this (and we can't have Java beating C++
> in speed, can we?).

Motivation exist when it improves SPEC numbers.

>> Even considering cross module inlining. With the same argument, you
>> don't need "inline" (I am not saying we'd get as much benefit as with
>> inline, I am just questioning the argument).
>
>> Of course, "with tomorow's compilers..."
>
> With some of today's compilers.  David Vandervoorde sent me an article
> at least four years ago which described such a compiler.

I have seen articles describing run time partial evaluation in C/C++,
with working implementation and clear benefit before that.
Still, it is not widespread, so maybe we do live in a complex world :-)

>  For years ago isn't tomorrow.

Provided you can get the article to compile your code.

(Note that I used that feature for a fraud^M^M^M^M benchmark, which
indicate I know about its existance, I know that you know that I know
but still :-)).

>  If such compilers aren't widespread, it is simply
> because there is no demand for them.  Partially, of course, because most
> applications don't need that sort of optimization.  But also because a
> number of companies seem to think it cheaper to spend man-years of
> effort hand tuning code rather than to pay, say $5000 a seat more for a
> compiler.

That's one reason, another could be the (percieved) cost of the
optimisation (time, bugs, less conservative optimizations). Another
could be the need to mix with third party libraries.

>> >> It might be used to indicate that the class is not written in a way
>> >> that makes general derivation safe; it might indicate that this is
>> >> my code not your code, and I don't want you extending it because
>> >> you haven't arranged for that right with me, or it might see use
>> >> when every possible optimization is needed.  The latter is the main
>> >> justification for it in Java.
>
>> > I don't think I've ever seen final used for optimization in Java.
>> > The most frequent use at the class level is simply to document that
>> > the class really should have value semantics, but since Java doesn't
>> > support this...  There is a proposal (from Gosling) concerning
>> > optimization, but it involves a new keyword (immutable, I think):
>> > not only must the class be final, but it must have no mutating
>> > (non-const in C++ speak) functions.
>
>> >> I don't know of a hue and cry against 'final' in Java, though I
>> >> suppose opponents could claim this is because final is so necessary
>> >> (Java performs hideously without it) that it has ceased to be seen
>> >> as evil.
>
>> > Java performs very well, thank you.  I've seen benchmarks where it
>> > beats C++.  Without using final.
>
>> For non numeric applications ?
>
> Only for applications which made extensive use of arrays (of basic
> types).  Not necessarily numeric, but not necessarily typical of all
> applications either.

So, basicaly, identify pointer alias analysis possible for one language
and not done in another and see how many iteration it takes to make it
faster ?
Well, I would have done the same if in the Java team :-)

>> I remember final making a difference in Java, it was a few years back
>
> I can remember when final would have made a difference, too.  But as you
> say, it was a few years back.  It doesn't seem to affect HotSpot.
>
>> (anyway, I have seen benchmarks showing purely symbolic languages
>> being faster than C, and I have seen how people did the benchmarks for
>> Java perf, those people cannot be trusted :-).
>
> Never trust a benchmark you haven't falsified yourself:-).  I did a
> benchmark which showed Java and g++ for Windows at about the same
> performance levels when I was at the Dresdner Bank.
>
> In the end, if final has some performance benefits, so much the better.
> But that certainly isn't the main reason for proposing it.

And I never claimed it was.

Alain

---
[ 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, 19 Dec 2002 20:09:29 +0000 (UTC)
Raw View
James Kanze wrote:
> You mean like operator overloading?

It's a matter of degree. If you can show me that
final would have one tenth the utility of operator
overloading, I might be convinced.

---
[ 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, 19 Dec 2002 20:14:24 +0000 (UTC)
Raw View
James Kanze wrote:
> You don't agree that ensuring class invariants
 > is a problem for C++ code?

You are making the assumption that no user of the
class will be able to extend it without breaking
the invariants. Some of us believe that it should
be up to the class users to decide this, not the
class designers. This is the "break my code"
versus "break your code" distinction.

Since I can derive a class and have the overriders
just call their base functions, it's always possible
to have a derived class which doesn't break invariants.

---
[ 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: brangdon@cix.co.uk (Dave Harris)
Date: Thu, 19 Dec 2002 21:15:25 +0000 (UTC)
Raw View
hyrosen@mail.com (Hyman Rosen) wrote (abridged):
> If you give the control freaks 'final', then derivers
> will have no chance to make their changes, correct or
> not. If you don't, then the onus is on the derivers
> to do things correctly, which is as it should be.

Today those control freaks make all their functions non-virtual and eschew
abstract base classes. For example, there are very few virtual functions
in the std library. Obviously designed by control freaks :-)

It occurs to me that "final" could /encourage/ dynamic polymorphism,
rather than discourage it.

For example, none of the member functions of std::vector are virtual.
Quite right too - concrete classes should be efficient. However, in C++ as
it stands, this means std::vector cannot have a pure abstract base class
with virtual methods, because there is no way to turn off the virtualness.

With final, we have more design options. We could have a hierarchy like:

    class vector_base {
    public:
        virtual int size() const = 0;
        // ...
    };

    class vector_impl : public vector_base {
    public:
        virtual int size() const;
        // ...
    };

    class vector : public final vector_impl {
    public:
        // ...
    };

Here vector_base is a pure abstract class which clients can inherit from
if they want to conform to the vector protocol while providing their own
implementation. Ideally deque and vector would use a common base class at
this level.

Vector_impl provides an implementation, which subclasses can reuse, but
all its methods are virtual so subclasses can override them if they
require special semantics.

And finally vector is a concrete class. Clients shouldn't derive from it.
It needs no dynamic dispatch. A good compiler should produce code as
efficient as for today's std::vector. (I appreciate this is a challenge,
especially if we want to eliminate the space overhead of the vtable
pointer too.)

std::vector is probably a bad example, but I hope you get the idea.


  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."

---
[ 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, 19 Dec 2002 21:53:46 +0000 (UTC)
Raw View
Dave Harris wrote:
> std::vector is probably a bad example, but I hope you get the idea.

Yes. OK, let's do it!

Actually, your example brings me back to the other feature
of Java that I wish C++ would have, which is "sideways"
overriding of abstract methods.

     struct vector_interface { virtual int size() const = 0; };
     struct vector { int size() const; };
     struct vector_with_interface : vector_interface, vector {
         // Let vector::size() override vector_interface::size()
     };

You know, I just had a thought. We can't really do it because
of backward compatibility, but it occurs to me that if C++ had
required "virtual" all the way down an inheritance hierarchy,
we could achieve your desired effect by allowing it to be left
off. The semantics would be that if a function was declared
virtual in a class, then calling that function using a pointer
or reference to that class would use virtual dispatch. Otherwise,
the function would be called directly. But derived classes could
still override it if they wanted, using virtual or not.

    class vector_base {
     public:
         virtual int size() const = 0;
         // ...
     };

     class vector : public vector_base {
     public:
         /* "final" */ int size() const;
         // ...
     };

     class instrumented_vector : public vector {
     public:
         virtual int size() const;
         // ...
     }

---
[ 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: brangdon@cix.co.uk (Dave Harris)
Date: Thu, 19 Dec 2002 21:57:20 +0000 (UTC)
Raw View
allan_w@my-dejanews.com (Allan W) wrote (abridged):
> Calling a virtual function 100 million times caused the program to
> run 4.406 seconds slower; in other words, each virtual function call
> took an additional 44.06 nanoseconds over a comparable non-virtual
> call. Surely this would have no measurable impact on real programs.

If this is true, perhaps the next version of the standard should make all
its member functions virtual.

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."

---
[ 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: allan_w@my-dejanews.com (Allan W)
Date: Thu, 19 Dec 2002 22:21:54 +0000 (UTC)
Raw View
> Peter Dimov wrote:
> >>void f(X final const & x);
> >>void g(X const & x) { f(x); }
> >>g(Y());

hyrosen@mail.com (Hyman Rosen) wrote
> Hmm. As usual, we find that Ada has been there,
> done that. In Ada, there is a distinction made
> between declaring things to have a specific type
> and declaring them to have "classwide" type.

Such a distinction could also be useful to solve the pointer/array
problem. Everyone here probably knows about the double-meaning of
pointer:

    struct Base { ... void bar(); ... };
    struct Der : public Base { ... };
    void foo(Base*b, int size) { ... b[1].bar(); ... }
    int main() { Der*d = new Der[5]; foo(d,5); delete[] d; }

Compiles without error, but blows up in foo().

If we had two types of pointer, we could solve this problem.

    "Pointer to actual type" could point to an object whose
    most-derived type is known at compile time, or an array of
    such objects. Pointer arithmetic would work as expected, as
    would array-style dereferencing, but upcasts would require
    an explicit cast (i.e. can't pass Der* to a function
    taking Base* without explicit casting). However, when passing
    an array to a function, the array name would convert to a
    "Pointer to actual type". Operator new would return a pointer
    to actual type, and operator delete would require one.

    "Pointer to classwide type" could point to an object of any
    given type, or anything derived from it, but not to a whole
    array. (It can point to one specific member in an array, though.)
    Pointer arithmetic and array-style dereferencing would be illegal,
    but upcasting would work as expected (i.e. can pas Der* to a
    function expecting Base* without explicit cast). operator new[]
    would return a pointer to classwide type, and operator delete[]
    would require one.

In the code above, foo's argument b would have to be declared as a
"pointer to actual type," but main's variable d would be declared
as a "pointer of classwide type." You wouldn't be able to pass this
to foo without a cast, so the program would not compile.

Still need some tuning of the rules, though; as it's written,
    Base * b = new Base;
would be required to make b a "pointer to actual type" when it ought to
also work with "Pointer to classwide type." But you get the gist...

Syntax isn't important, but please note that support from legacy code
would best be supported with not two but THREE types of pointers.
(The third one would be called a "legacy pointer" but it would be
deprecated.) Perhaps we could add new keywords just before (each of)
the *'s in an expression, as in

    Foo polyptr* baz[50];
    Foo monoptr* bar[50];
    Foo        * bat[50];

Here baz is an aray of 50 pointers-to-classwide Foo objects ("PolyPtr"
because the pointer is polymorphic (but can't support arrays), and

bar is an array of 50 pointers-to-actual Foo objects ("MonoPtr" because
it's monomorphic -- is that a word? Should it be antimorphic, or
nonmorphic, or what?).

bat is an array of legacy pointers to Foo objects. They can do anything
that they used to do -- but good compilers will print a warning (that
can be turned off, of course).

> Dispatching happens only on objects or pointers
> of classwide type, not on objects of actual type.
> (That is, if you have a class Base, and an object
> of type Base or pointer to Base, the methods
> invoked are those of Base only. If you have an
> object or pointer of type Base'class, then
> dispatching will happen if the the object is of
> derived type.)

Meaning virtual dispatch, right? You can still call methods in
the class, but it's a direct call.

---
[ 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: allan_w@my-dejanews.com (Allan W)
Date: Thu, 19 Dec 2002 22:37:56 +0000 (UTC)
Raw View
francis.glassborow@ntlworld.com (Francis Glassborow) wrote
> Hyman Rosen <hyrosen@mail.com> writes
> >Francis Glassborow wrote:
> >> Once we have started we cannot stop.
> >
> >Correct, and the question becomes whether the
> >ability to stop is important enough to warrant
> >the inclusion of final into C++, given that
> >many of us think that it will be more misused
> >than used appropriately.
>
> The adjective 'arrogant' has been used in this thread, I might add
> 'paternalistic'. Could we stick to the technical merits of a proposal.

That certainly has been true in this thread -- but Hyman's words
above are NOT a good example of it. If he really believes that a
proposed change will cause more bad code than good code, that
certainly counts as a technical merit (or lack of merit)!

You seem to believe that "protecting the programmer against himself"
is a bad thing, at least in this particular case. That's your
opinion, but calling Hyman 'paternalistic' doesn't help to convince
anyone of anything.

I almost expected to see that you had approved this posting yourself --
certainly it comes close to violating the group guidelines?

---
[ 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: allan_w@my-dejanews.com (Allan W)
Date: Fri, 20 Dec 2002 00:33:50 +0000 (UTC)
Raw View
kanze@gabi-soft.de (James Kanze) wrote
> The main concrete con that I have heard mentionned was the limitations
> with regards to some fancy metaprogramming techniques.  The fact that
> something can be misused has never been an obstacle to incorporating it
> into C++ (although the fact has been mentionned).

I can't name a case off-hand where it has blocked a feature. But it has
certainly been a factor!

Overall, the C++ committee had better think that a new feature helps
a lot more than it hurts -- or else they had better not add it to the
language.

(For instance, we could require that all C++ programs need a
possibly-empty "Identification division" just like COBOL. This would cause
very little harm -- but no good at all, AFAIK. Therefore, I hope that the
committe does NOT do this.)

---
[ 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: allan_w@my-dejanews.com (Allan W)
Date: Fri, 20 Dec 2002 00:34:01 +0000 (UTC)
Raw View
> > > Alain Miniussi wrote:
> > >> This looks like the argument usually made for inline

> > Hyman Rosen wrote:
> > > I expect James Kanze can tell you what he considers best practice
> > > with respect to that :-) I doubt that it includes willy-nilly
> > > inlining of everything.

> alain@miniussi.net (Alain Miniussi) wrote
> > I remember reading that his principles were relaxed when it came to
> > one liner where the inlined code would be shorter than the call.

kanze@gabi-soft.de (James Kanze) wrote
> You read wrong.  Or you read something I wrote some years back.

But certainly it makes sense -- not neccesarily for a "one liner"
(after all, you can put some very complicated calculations on one
line!) but for functions I would call "Trivial". To me, a trivial
function is one that returns data already stored in an easily-accessed
variable. For instance, a function in a Customer object that returns
the customer's name as a string, if the Customer object has that data
in a member variable.

The logic goes like this: the amount of generated machine code from a
function call is very small, but still greater than zero. The code
involved in passing an argument back to the caller is also nonzero.
Experience has shown that accessing a private variable through an
"access
function" like this is generally almost identical to accessing a
public
variable directly. If you're going to use this type of access function
(and that's a seperate debate in it's own right), you should go ahead
and
make them inline -- this still preserves encapsulation, because at
some
future date you can change the definition of the function (and make it
not inline anymore), and client code does not need to change (just
recompile).

In cases where I've done performance tests or examined the generated
machine code, making functions this trivial have ALWAYS been either
equal
or better than making them not-inline. That's not conclusive proof
that
it always will, but it's strong circumstantial evidence to that
effect.

> The more I use C++, the less I make inline. My current policy is to
> make nothing (and I mean absolutely nothing) inline, however,

We both agree that premature optimization is a bad thing -- until
you've
seen the profiler, even experts will pick the wrong places for
optimization,
and very often will end up de-optimizing.

However, there are a very few things that we can do by rote, with the
full
knowledge that it will always be either better or equivalent. A simple
example is using prefix++ insteazd of postfix++. Another example is to
inline trivial functions.

> so I doubt
> that this trend will continue.

Have you established criteria about what and when to change?

> What this has to do with final, however, I don't know.

Agreed.

---
[ 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: kuyper@wizard.net ("James Kuyper Jr.")
Date: Fri, 20 Dec 2002 03:38:26 +0000 (UTC)
Raw View
Pete Becker wrote:
....
> Sure, if someone does it. The problem is that people present the outline
> for a discussion as if it were complete and conclusive. And oddly
> enough, these demonstrations always ending up supporting the position of
> the person who presents them.

So, could you provide an example of what form the missing details would
take, if they were present? All I can tell from what you've said so far
is that something you think should be there is missing.

---
[ 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: scottm@toast.net ("Scott Mayo")
Date: Fri, 20 Dec 2002 03:38:46 +0000 (UTC)
Raw View
"Hyman Rosen" <hyrosen@mail.com> wrote in message
news:8LaM9.48635$4W1.13805@nwrddc02.gnilink.net...
> Francis Glassborow wrote:

> > The adjective 'arrogant' has been used in this thread, I might add
> > 'paternalistic'. Could we stick to the technical merits of a proposal.

> We are debating a feature that will enable programmers to be
> arrogant and paternalistic.

As is already their right. I don't recall an ANSI mandate that requires
languages to cater only to the passive and child-like. If I choose to
dictate
how my classes may be used, why is that de facto wrong? If it's wrong,
why is private: tolerated, and why are all destructors not automatically
virtual?

No one has convinced me that final is different than const or private:.
All of them say "Thou shalt not" to some aspect of the language that
more commonly says "sure, go for it." All of them supply the compiler
with additional information, which can be used to enhance optimization
and help prevent careless errors. private: especially, is inarguably a way
to keep people out of things that will break if touched; the arguments
about why final is arrogant strike me as just as applicable to private:,
but I think everyone here agrees that private: is Pure Goodness(tm).

If I argued "private: is bad, for as user of your class I alone should
be allowed to determine for myself if that member variable is useful
to me or not; so let's make private: just mean protected:" -- what
would the response be?

I'd expect to be lynched (but courteously, of course).



---
[ 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: Fri, 20 Dec 2002 06:43:57 +0000 (UTC)
Raw View
Scott Mayo wrote:
> As is already their right.

I think it was David Abrahams who finally set me on the right path.
I now know the type of 'final' which is acceptable to me, and which
I think strikes a good balance of control. My version applies only
to functions, and its effect is to turn off virtual dispatch for
calls to that method through references and pointers of that class.
I think the keyword should be '~virtual' rather than 'final'. The
method can still be overridden in derived classes, and can be made
virtual, or not, there.

This takes care of the optimization issue, the vistor issue, and
most of the invariant issue, while still allowing the methods to be
overridden by someone who really wants to and knows what he's doing.

---
[ 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: kanze@gabi-soft.de (James Kanze)
Date: Fri, 20 Dec 2002 16:33:32 +0000 (UTC)
Raw View
hyrosen@mail.com (Hyman Rosen) wrote in message
news:<1040328325.912760@master.nyc.kbcfp.com>...

> James Kanze wrote:
> > You mean like operator overloading?

> It's a matter of degree. If you can show me that final would
> have one tenth the utility of operator overloading, I might be
> convinced.

It depends on your application domain.  If you aren't really
worried about correctness, and enforcing class invariants, final
has no use at all.  If you don't need user defined numeric
types, the ability to overload the numeric operators is of no
use at all.

In my telephone applications, I didn't have any user defined
numeric types, and program correctness was critical.  Final
would be far more useful than operator overloading.  In my
banking applications, I need decimal numbers, and while we like
things to be correct, it isn't carried to the same extreme as in
the telephone applications.  Operator overloading is more
useful, although final would still be useful.  (And as luck
would have it, the largest banking application was done in Java,
where I had, and used, final, but didn't have operator
overloading, and was obliged to write things like value.add(
value.multiply( vat ) ).)

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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: kanze@gabi-soft.de (James Kanze)
Date: Fri, 20 Dec 2002 16:34:41 +0000 (UTC)
Raw View
petebecker@acm.org (Pete Becker) wrote in message
news:<3E01EC13.D8CC31DD@acm.org>...
> James Kanze wrote:
> > hyrosen@mail.com (Hyman Rosen) wrote in message
> > news:<1040226478.583165@master.nyc.kbcfp.com>...

> > > Scott Mayo wrote:
> > > > I dislike Java too, but I'm not willing to dismiss an
> > > > entire language out of hand. It turns out that Java has
> > > > a structure roughly similar to C++ in terms of classes,
> > > > and 'final' has the same semantics as it would in
> > > > C++. 'final' solves a problem in Java (even if you don't
> > > > agree that there is such a problem)

> > > This has nothing to do with liking or disliking Java.
> > > While the class structure of C++ and Java are roughly
> > > similar, 'final' solves a problem for Java that exists
> > > only in Java, at a place where the differences in class
> > > structure show up.  We don't agree that there is an
> > > equivalent problem in C++, and therefore the presence of
> > > 'final' in Java is not (useful) prior art for C++.

> > You don't agree that ensuring class invariants is a problem
> > for C++ code?

> Of course everyone agreees with that. The real issue in this
> area is what does final contribute to solving this problem.

My concrete experience with final in Java is that it does help.

It's probably less essential in C++, because you have many cases
where the correct solution is just to not make the function
virtual to begin with.  But there are exceptions, for example
when the implementation of an interface uses the template model.

How important this case is depends on the application domain; I
can quite imagine that in certain domains, it never occurs.  But
I've encountered it several times.  Certainly more often than
I've used double, for example.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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: kanze@gabi-soft.de (James Kanze)
Date: Fri, 20 Dec 2002 16:35:06 +0000 (UTC)
Raw View
gdr@integrable-solutions.net (Gabriel Dos Reis) wrote in message
news:<m3r8ceezvi.fsf@uniton.integrable-solutions.net>...
> kanze@gabi-soft.de (James Kanze) writes:

> [...]

> | You don't agree that ensuring class invariants is a problem
> | for C++ code?

> I didn't see anyone disputing that; did you?

Yes.  I was responding to a posting which said that the problems
final solves in Java don't exist in C++.  The major problem
final solves in Java is enforcing class invariants.

> I believe that one of the key issues is about the real (not
> supposed) contribution of "final" in solving that problem.

Well, I can only guess for C++.  For Java, I know from concrete
experience that we regularly declared about half the functions
in the derived class final, in order to ensure our class
invariants.  It worked, and without final, we couldn't have
ensured the class invariants.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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: kanze@gabi-soft.de (James Kanze)
Date: Fri, 20 Dec 2002 16:35:51 +0000 (UTC)
Raw View
alain@miniussi.net (Alain Miniussi) wrote in message
news:<v045f6sb13qi0b@corp.supernews.com>...
> James Kanze wrote:

> > alain@miniussi.net (Alain Miniussi) wrote in message
> > news:<v0226hrbfadec4@corp.supernews.com>...
> >> Hyman Rosen wrote:

> >> > Alain Miniussi wrote:
> >> >> This looks like the argument usually made for inline

> >> > I expect James Kanze can tell you what he considers best
> >> > practice with respect to that :-) I doubt that it
> >> > includes willy-nilly inlining of everything.

> >> I remember reading that his principles were relaxed when it
> >> came to one liner where the inlined code would be shorter
> >> than the call.

> > You read wrong.

> I would says that's unlikely, I remember it struck me comming
> from you :-)

> > Or you read something I wrote some years back.

> That's likely.

But many years back.  I haven't given a thought about code size
now for I don't know how long.

I believe that this was the rule in the original Henricson and
Nyquist coding guidelines.

> > The more I use C++, the less I make inline.  My current
> > policy is to make nothing (and I mean absolutely nothing)
> > inline, however, so I doubt that this trend will continue.

> [..]
> > What this has to do with final, however, I don't know.  I
> > can't remember ever seeing a performance problem due to
> > virtual function calls, when the function should have been
> > virtual in the base class.  > > But others did, if final can
> > helps them, what argument can be opposed ?

> >  (Obviously, if you declare the operator[] in vector
> > virtual...)  And there is a simple solution

> But it can be miss-used (ok, that's unfair) :-)
> Now, wouldn't final simplify that solution ? (and maybe make
> it safer by preventing ReallyConcreteConcreteArray from
> overriding doIndex ?).

Certainly.  I'm in favor of final.  I just don't see any need
for specious arguments to support it.  Final is useful for
enforcement of class invariants.  It helps to write correct
code.

At least, that is my experience, with final in Java.  And many
of the times we applied final in Java, it was to a function
which overrid a function in the base class -- just making the
function non-virtual wasn't an option.

> > (which I regularly used in my pre-standard array classes):

> >     template< typename T >
> >     class AbstractArray
> >     {
> >     public:
> >         T&                  operator[]( int index )
> >         {
> >             return doIndex( index ) ;
> >         }

> >     private:
> >         virtual T&          doIndex( int index ) = 0 ;
> >     } ;

> >     template< typename T >
> >     class ConcreteArray

> Did you forgot a derivation ?

Obviously.

> >     {
> >     public:
> >         T&                  operator[]( int index )
> >         {
> >             //  The real implementation...
> >         }
> >
> >     private:
> >         virtual T&          doIndex( int index )
> >         {
> >             return operator[]( index ) ;
> >         }
> >     } ;

> [..]

> > I repeat: the optimization issue is a red herring with
> > regards to final.  The real issue is whether you think the
> > author of a class should be in charge of his class
> > invariants, or whether you think that anyone who might want
> > to derive from the class should be permitted to violate the
> > invariants arbitrarily.  Put that way, it sounds like the
> > answer is obvious.  To me it is, but surprisingly, I've run
> > into not a few people who insist that all functions should
> > be virtual.  Always.  Still, in C++, I think the general
> > trend is to recognize that at least some functions shouldn't
> > be redefinable.  Not for optimization reasons, but because
> > we want to be able to write correct code.  This is, after
> > all, one of the motivations (mine, at least) behind
> > forbidding public functions to be virtual in many cases.

> This is one (valid) tactique, but these are not everybody's
> choices (of course, establish which one is more common really
> depends on the sample you choose).

What is one valid tactique?

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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: kanze@gabi-soft.de (James Kanze)
Date: Fri, 20 Dec 2002 16:36:28 +0000 (UTC)
Raw View
allan_w@my-dejanews.com (Allan W) wrote in message
news:<7f2735a5.0212191628.48fbda62@posting.google.com>...
> > > > Alain Miniussi wrote:
> > > >> This looks like the argument usually made for inline

>  Hyman Rosen wrote:
> > > > I expect James Kanze can tell you what he considers best
> > > > practice with respect to that :-) I doubt that it
> > > > includes willy-nilly inlining of everything.

>  alain@miniussi.net (Alain Miniussi) wrote
> > > I remember reading that his principles were relaxed when
> > > it came to one liner where the inlined code would be
> > > shorter than the call.

> kanze@gabi-soft.de (James Kanze) wrote
> > You read wrong.  Or you read something I wrote some years back.

> But certainly it makes sense -- not neccesarily for a "one
> liner" (after all, you can put some very complicated
> calculations on one line!) but for functions I would call
> "Trivial". To me, a trivial function is one that returns data
> already stored in an easily-accessed variable. For instance, a
> function in a Customer object that returns the customer's name
> as a string, if the Customer object has that data in a member
> variable.

> The logic goes like this: the amount of generated machine code
> from a function call is very small, but still greater than
> zero. The code involved in passing an argument back to the
> caller is also nonzero.  Experience has shown that accessing a
> private variable through an "access function" like this is
> generally almost identical to accessing a public variable
> directly. If you're going to use this type of access function
> (and that's a seperate debate in it's own right), you should
> go ahead and make them inline -- this still preserves
> encapsulation, because at some future date you can change the
> definition of the function (and make it not inline anymore),
> and client code does not need to change (just recompile).

> In cases where I've done performance tests or examined the
> generated machine code, making functions this trivial have
> ALWAYS been either equal or better than making them
> not-inline. That's not conclusive proof that it always will,
> but it's strong circumstantial evidence to that effect.

That was my reasoning, before.  Since then, I've gotten tired of
recompiling the world because the implementation of one of these
"trivial" functions changed, which entailed a change in a header
file.

There are functions where it is more or less obvious that inline
is both a space and a time win.  But inline is never a win with
regards to compile time dependancies.  And in general, IMHO, the
win in space and time just isn't worth the loss with regards to
compile time dependancies.  (Until actual performance and the
profiler tell me otherwise, of course.)

    [...]
> Have you established criteria about what and when to change?

Yes.  When actual performance and the profiler tell me to
inline.  It is a cheap optimization, once the program is stable.

And of course, these rules apply to my work, which is mostly on
large and very large applications.  If you're writing a standard
library, of course, you aren't going to wait until your
customers come complaining about performance to inline
vector::operator[].  And it is possible that in certain specific
domains, maybe numeric processing or games programming, that you
know in advance that certain specific functions are probably hot
spots, and adopt different rules.  But as a general rule, when
writing applications, you don't use inline functions.  (I have
even started declaring and defining things that the compiler
will generate correctly by default.  Simply because I don't want
to trigger a compile of the world the day the compiler generated
default is no longer appropriate.)

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Fri, 20 Dec 2002 16:56:10 +0000 (UTC)
Raw View
In article <7f2735a5.0212191628.48fbda62@posting.google.com>, Allan W
<allan_w@my-dejanews.com> writes
>But certainly it makes sense -- not neccesarily for a "one liner"
>(after all, you can put some very complicated calculations on one
>line!) but for functions I would call "Trivial". To me, a trivial
>function is one that returns data already stored in an easily-accessed
>variable.

How about a pure forwarding function which will generate zero code? Such
things as functions that ensure const correctness which simply allow the
compiler to call the const version and return a non-const
reference/pointer based on one of the parameters.

Of course a modern linker can probably do that optimisation for you but
I cannot see that it is wrong (or premature) to do it explicitly.


--
Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ 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: llewelly.@@xmission.dot.com (llewelly)
Date: Fri, 20 Dec 2002 16:56:40 +0000 (UTC)
Raw View
kanze@gabi-soft.de (James Kanze) writes:

> llewelly.@@xmission.dot.com (llewelly) wrote in message
> news:<86el8hjkcw.fsf@Zorthluthik.foo>...
> > kanze@gabi-soft.de (James Kanze) writes:
> > [snip]
[snip]
> > I strongly suspect most of those supporting final have not thought
> > of preserving class invariants, and are trying to solve a quite
> > different problem, which your suggestion does not address. (I agree
> > that the problem you describe is real, and could be solved by the
> > mechanism you suggest - I just think most of the other posters here
> > are not thinking about it when they think of 'final'.)
>
> What other use could it have in C++?

I suspect many many features of C++ have become part of some idiom that
    no designer of said feature considered.

>
> I base my comments on my experience in Java -- in user code, all of the
> use we made of final was to preserve class invariants.

The issues with non-virtual destructors, assignment operators, etc, do
    not arise in Java (so far as I know). If C++ got a final that
    prevented all public inheritance (as opposed to your suggestion of
    only preventing the overriding of virtual functions), I am nearly
    certain it would be used for classes with non-virtual destructors,
    etc, to prevent the problems I mentioned.

[snip]
> > By use of such things as non-virtual destructors, assignment
> >     operators, swap members, cast operators, etc, it is possible to
> >     create a class (call it Base) such that a class Derived which is
> >     derived from Base has some error-prone behavior when used
> >     polymorphicly. The classic example is deleteing an object with a
> >     non-virtual destructor, using a pointer that is not of the
> >     object's exact type. I believe these kinds of classes are in fact
> >     the primary bone of contention between the want-finals and the
> >     not-want-finals.
>
> I want final, but I don't see any real problem here.

You want a different kind of final. You want something I'll call
    do_not_override. It is more specific (and probably better suited
    to C++) than a naive importation of java's final.

I'm unsure of how (un)common the probablems I mention are. I used to
    see them all the time when I did C++ tutoring in school. I mention
    them because they are frequently cited examples of why C++ should
    have a means for preventing inheritance. I don't think
    preventing inheritance is a good way to solve those problems; I
    don't see them often in my work as a programmer. Perhaps they are
    best solved by education. But it's silly to expect non-virtual
    destructor like problems to not be raised in a discussion about
    final, and of course people have reason to ask for a
    language-supported mechanism for solving these problems. (Hyman's
    mention of Ada's two types of pointers, the kind which supports
    polymorphism, and the kind that doesn't, is an intriguing
    possibility.)

[snip]
> Before this thread, I'd have probably said OK to a final blocking
> inheritance anyway;

Then this thread has done some good.

> several posters, however, have show important idioms
> involving derivation (for other reasons that the usual isA relationship)
> from arbitrary classes (or event types? -- maybe the rules should be
> extended to allow derivation from the basic types).  Given this, I would
> argue against blocking these idioms (even though I don't currently use
> them) just to catch some errors which are, statistically speaking, rare.
>
> But I'm left with the problem of ensuring class invariants.  And that is
> important, at least to me.  As I said, in Java, I ended up declaring
> most functions final.
>
> A typical case of where it is important to declare a virtual function
> final is when the implementation of an interface uses the template
> pattern.  Because of the template pattern, the implementation class will
> be a base class for further derivation.  The implementation overrides
> the virtual function in the interface, and provides a new set of virtual
> functions for the further derived classes to override.  The further
> derived class should NOT, however, override the functions declared in
> the base interface.
>
> This particular case occurred three or four times in my last Java
> application.

I'll agree with this section - some time ago I spent a few weeks
    working on a java-servlet implemented e-commerce app. I saw that
    idiom a number of times. I'd forgotten until you mentioned it,
    though, as I've gone some months without using Java.

I think I like your do_not_override suggestion.

[snip]
> In the end, I like Pete Becker's position: I want to prevent things
> which can break MY code, but my client's code is his responsibility.
> This is overstated: if I can easily trap some stupid client errors, so
> much the better.  But it shouldn't come at the price of preventing some
> valid uses.

That part of Pete's position I like and agree with. However I'm
    disappointed that he (seems) unwilling to reason with those who
    differ with him; he just says (approximately) 'over my dead
    body'. On the other hand, he's likely sick and tired of hearing
    about final - I know I often don't read threads on final.

> Maintaining class invariants is essential in order to avoid breaking my
> code.

And in the case of the non-virtual destructor problem, it could be
    argued that code which uses a derivitive of such a class is
    relying on an invariant the base class does not pretend to
    preserve.

[snip]

---
[ 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: kanze@gabi-soft.de (James Kanze)
Date: Fri, 20 Dec 2002 16:57:36 +0000 (UTC)
Raw View
fjh@cs.mu.OZ.AU (Fergus Henderson) wrote in message
news:<atmp1l$qmt$1@mulga.cs.mu.OZ.AU>...
> kanze@gabi-soft.de (James Kanze) writes:

> >I think Dave Harris hit the nail on the head when he spoke
> >about preventing overriding of functions.  Normally, the only
> >danger to my code when you inherit from my class is that you
> >override some of the virtual functions, but not all, and that
> >the virtual functions work together to ensure class
> >invariants.

> It's not just that.  There's also the issue of passing a
> derived class where a base class is expected, which can break
> the preconditions of functions like swap() which expect that
> their arguments point or refer to the class specified, not to
> a derived class with additional data members.

But that affects all derived classes, not just the ones where I
might want to prevent derivation.

I don't know if this is a real problem or not, but if it is, it
is easy to fix:

    template< typename T >
    void
    swap( T& a, T& b )
    {
        assert( typeid( a ) == typeid( T )
                && typeid( b ) == typeid( T ) ) ;
        //  ...
    }

It's not a compile time solution, but I'm not convinced that a
complete compile time solution is possible.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Thu, 12 Dec 2002 20:23:21 +0000 (UTC)
Raw View
Francis Glassborow wrote:
>
> In article <3DF8C945.7E447987@acm.org>, Pete Becker <petebecker@acm.org>
> writes
> >Peter Dimov wrote:
> >>
> >> francis.glassborow@ntlworld.com (Francis Glassborow) wrote in message news:<4M2$lbBI2w99Ewit@robinton.demon.co.uk>...
> >> > No library designer would be compelled to use final were it available.
> >>
> >> Some of us are afraid that this would not be the case.
> >
> >Indeed. If it goes into the language, someone's going to stand up at a
> >standards meeting and propose that we go through the standard library
> >and mark all the classes that "should" be final.
>
> I see, even those designing the language cannot be trusted.

Despite starting with "I see," this doesn't seem to have anything to do
with what I said.

> I think that
> the overwhelming majority of our colleagues are better than that.

Better than what?

>
> Actually, one feature is that no published class can be declared final
> as that would potentially break existing code and therefore, whilst
> favouring at least experiments with final I would also oppose applying
> it to any element of the existing Standard C++ Library. And I am certain
> that that would be the general consensus.
>

What? You mean there is code out there that derives from classes that
shouldn't be derived from? How can that code can possibly work right?
Heavens to Betsy, what shall we do?

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Thu, 12 Dec 2002 22:23:26 +0000 (UTC)
Raw View
In article <7dc3b1ea.0212120750.13dc5d4c@posting.google.com>, Peter
Dimov <pdimov@mmltd.net> writes
>The point of the above is that I'll have to worry about final classes
>breaking my libraries, regardless of whether I buy something or not.

Then you should already be worrying. Scott Meyers has maintained for
nearly a decade that 'in general' deriving from a leaf class (or more
precisely, any non-abstract class) is a design error. I can remember
arguing with him on that issue at a SIGS conference in the UK in 1992 or
93.

Couple that with the already existing mechanisms for preventing
derivation becoming steadily more widely known and the problem you fear
is already out of the bag.

Final would at least allow you to document that your classes and
templates will not work with final classes.

--
Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ 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: brangdon@cix.co.uk (Dave Harris)
Date: Thu, 12 Dec 2002 23:29:36 +0000 (UTC)
Raw View
francis.glassborow@ntlworld.com (Francis Glassborow) wrote (abridged):
> By the way, there seems to be confusion in some peoples minds as to
> what this is being applied to.

Yes :-)


> I am not interested in finalisation of
> virtual methods and finalisation of virtual bases is both confusing and
> not a feature that could be tried and then removed (without cost). What
> I am in favour of (and I think quite a few others are) is the ability
> to declare that a class is a 'leaf class', i.e. cannot be used as a
> base class.

I am the other way about. I think it would be useful to declare individual
routines as final, to lock in a particular implementation. The benefits
would be similar to not declaring it virtual in the base class. The code
becomes easier to analyse, easier to ensure correct, easier to make fast.

I see final applied to a class as a short-hand for making all its routines
final. I don't see much need to prevent inheritance from such a class,
although because it now has a non-virtual destructor inheritance would
have to be used with care. Inheriting from a final class would be about as
useful as inheriting from a POD or std::vector.

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."

---
[ 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: brangdon@cix.co.uk (Dave Harris)
Date: Thu, 12 Dec 2002 23:29:44 +0000 (UTC)
Raw View
hyrosen@mail.com (Hyman Rosen) wrote (abridged):
> You can now riposte with the objection that there could be many
> such templates, and they would all have to be specialized.

Indeed. This is especially important when final is used as a tactical
optimisation, because such should have minimum impact on working code.


> But how much real code out there needs this?

I have no idea. Certainly this is not at the top of my "new C++ features"
list.


> > Even without templates, we may not want to hand-edit megabytes
> > of code looking for places where foo() can be changed to final_foo().
>
> But without templates, all those places must be written in terms of
> base objects. None of them could be so changed!

Not so. Some of them could be written in terms of references to Derived.

   void Demo( Derived &t ) {
       t.foo();
   };

It'd certainly be possible to rewrite this as:

   void Demo( Derived &t ) {
       t.Derived::foo();
   };

It's just painful to do so.

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."

---
[ 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: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Thu, 12 Dec 2002 23:30:00 +0000 (UTC)
Raw View
In article <3DF8E9D0.6CB0047F@acm.org>, Pete Becker <petebecker@acm.org>
writes
>"Available as bases" means something rather different from "usable as
>bases." And, of course, whether it's an abuse is in the eye of the user.

Perhaps American gives a different meaning to 'usable' than that which
it has in English. :-)

Usable means 'can be used' this side of the Atlantic. Or even 'Is
available for use'


--
Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ 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: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Thu, 12 Dec 2002 23:30:11 +0000 (UTC)
Raw View
In article <3DF8EE99.AFDD8A34@acm.org>, Pete Becker <petebecker@acm.org>
writes
>What? You mean there is code out there that derives from classes that
>shouldn't be derived from? How can that code can possibly work right?
>Heavens to Betsy, what shall we do?


The same thing we are currently doing with vector<bool>.

And you know very well that I did not claim that there were any such
classes in the Standard Library, just that that horse has left the
stable. That is not a reason for not providing optional doors with bolts
in the designs of future stables.


--
Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Fri, 13 Dec 2002 01:38:53 +0000 (UTC)
Raw View
Francis Glassborow wrote:
>
> In article <3DF8EE99.AFDD8A34@acm.org>, Pete Becker <petebecker@acm.org>
> writes
> >What? You mean there is code out there that derives from classes that
> >shouldn't be derived from? How can that code can possibly work right?
> >Heavens to Betsy, what shall we do?
>
> The same thing we are currently doing with vector<bool>.
>

Last time I looked we weren't doing anything with vector<bool>. Did I
overlook a proposal, or are you using the royal we?

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: allan_w@my-dejanews.com (Allan W)
Date: Fri, 13 Dec 2002 01:39:24 +0000 (UTC)
Raw View
dave@boost-consulting.com (David Abrahams) wrote
> francis.glassborow@ntlworld.com (Francis Glassborow) writes:
> > Peter Dimov <pdimov@mmltd.net> writes
> >>In the absence of documentation explicitly saying "though shalt not
> >>derive", derivation from a class is perfectly legal, and not a bug.
> >>You must not diagnose it. How many of your classes make that claim in
> >>their documentation? My guess is that none do, and this is exactly as
> >>it should be, since derivation is not a mistake by itself.
> >
> > And that is exactly what Fergus et al. have been
> > challenging. Sometimes derivation can be a mistake by itself because
> > the class designer/implementor knows that the class needs to make
> > assumptions about pointers and references that would be broken if
> > they happened to point/refer to an instance of a derived type.
>
> He didn't show an example of that, though.  At least, not one which
> stands up to Peter's question about operator=().

The real argument in favor of preventing derivation, seems to be that
not all classes have virtual destructors. Virtual destructors are
vitally important if the class is used polymorphically, but not all
derivation is for the purpose of polymorphism (i.e. it may be safe
to derive your own class from std::vector or std::string, so long as
you never try to delete the object via the base class destructor).

Maybe what we really need is the ability to make a compile-time
assertion that some class has a virtual destructor.

    MyClass *c = MyClassFactory("abc"); // Returned object might be
                                        // something derived from MyClass
    ... use c ...
    ASSERT_VIRTUAL_DESTRUCTOR(c);
    delete c; // Safe

---
[ 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: comp.std.c++_2002-12-13@nmhq.net (Niklas Matthies)
Date: Fri, 13 Dec 2002 01:39:28 +0000 (UTC)
Raw View
On 2002-12-09 01:18, Pete Becker <petebecker@acm.org> wrote:
> Niklas Matthies wrote:
>>
>> What exactly is the fundamental difference you seem to see, that goes
>> beyond an arbitrary convention? Continuing to repeat the above like a
>> mantra doesn't really explain anything.
>
> Thank you for asking. You're the first to not just say "you're wrong."
>
> You design and implement a class so that it works correctly (modulo
> errors, of course). You make things private if uncontrolled changes to
> them will violate your class's invariants, which would violate the
> assumptions underlying your interface functions.

What if one of those assumptions is that no instance of that class is
ever the base part of larger object of derived type?

> So you prevent access to those things in order to make sure that your
> code (the code you wrote to implement the class) works correctly.
>
> If someone derives from your class in a way that doesn't make sense that
> doesn't affect your code. It still works right.

Not necessarily. For a trivial example, place 'assert(typeid(*this) ==
typeid(my_class));' into some method. For a less trivial example,
consider a class whose objects always register themselves with some
facility that only can handle objects with a fixed set of typeids, or
with a give size, maybe for purposes like garbage collection.

Making a class 'final' specifically means that the author doesn't
(want to) guarantee that instances of his class will work when they
occur as a base part of objects of types derived from that class.

I still don't see the crucial difference to the case where the author
doesn't guarantee that his class will work when client code accesses
specific members.

-- Niklas Matthies

---
[ 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: allan_w@my-dejanews.com (Allan W)
Date: Fri, 13 Dec 2002 01:39:39 +0000 (UTC)
Raw View
terekhov@web.de (Alexander Terekhov) wrote
> Allan W wrote:
> > How about any class that implements
> > operator=() this way:
> >
> >     const Foo &operator=(const Foo&f) {
> >        if (this != &f) {
> >           Foo::~Foo();
> >           new(this) Foo(f);
> >        }
> >        return *this;
> >     }
> >
> > NOTE -- I'm not advocating this technique, so please don't tell me how
> > terrible this code is when Foo's constructor can throw, or how it just
> > isn't smart. The point is, this is the only legal way to implement a
> > complete operator= when the class contains a reference or a const member.
> > Furthermore, the C++ standard guarantees that this works, but not if it's
> > a base class -- which means it ought to be marked Final.
>
> Well, < for example >
>
> class Bar : Foo /* ... */ {
>   Bar& operator=(const Bar&); // unimplemented
>   /* ... */
> public:
>   /* ... */
> };

Would you say that Bar IS-A Foo? Because Foo objects can be assigned,
many people will be surprised that Bar objects cannot.

---
[ 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: comp.std.c++_2002-12-13@nmhq.net (Niklas Matthies)
Date: Fri, 13 Dec 2002 01:39:44 +0000 (UTC)
Raw View
On 2002-12-09 01:19, Pete Becker <petebecker@acm.org> wrote:
> Niklas Matthies wrote:
>> On 2002-12-05 19:43, Pete Becker <petebecker@acm.org> wrote:
>> > Niklas Matthies wrote:
>> >> On 2002-12-05 18:23, Pete Becker <petebecker@acm.org> wrote:
>> >> > Scott Mayo wrote:
>> >> [...]
>> >> >> Give me 'final'. Give me anything that will let me have
>> >> >> the *compiler* require that people follow the rules I
>> >> >> set down when I designed my classes, especially if it
>> >> >> also has a shot of improving optimizations.
>> >> >
>> >> > Why do you think you're better qualified to judge the code that someone
>> >> > else is writing than they are?
>> >>
>> >> With regard to derivation, the question is who is better qualified to
>> >> judge whether a class should or shouldn't be derived from: The author of
>> >> said class, or the programmer who merely wants to use that class as a
>> >> base for his own?
>> >
>> > The programmer who "merely" wants to derive from that class knows what
>> > he wants to use it for. The author of the class does not.
>>
>> Right, and the latter is the reason why the author might want to
>> disallow derivation.
>
> I don't follow this. If the author doesn't know what the programmer
> wants to use the class for, why should the author want to disallow
> derivation?

Because the author only wants his class to be used for certain purposes,
as he only designed it for those purposes, and since he doesn't know
what a programmer who derives from his class wants to use it for, the
author might like to disable derivation when he has no other means to
restrict derived classes to those cases that happen to be consistent
with said purposes. This is just as with 'private', were you deny all
outside accesses to a member, even those that wouldn't violate the class
invariants.

>> > The programmer is in a better position to know what he needs than the
>> > author of the class. Writing a class shouldn't turn you into a nanny.
>>
>> Why not? It's your class, after all.
>
> Yup, that's the bottom line, isn't it? Doesn't what users want; you
> wrote it, you decide what others can do with it.

Exactly. Do you think it's the language's job to prevent the original
author from making such decisions? Who is more presumptuous then, the
author who prevents his class from being derived from, or the language
that prevents the author from doing so?

-- Niklas Matthies

---
[ 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: allan_w@my-dejanews.com (Allan W)
Date: Fri, 13 Dec 2002 01:52:57 +0000 (UTC)
Raw View
> > terekhov@web.de (Alexander Terekhov) wrote
> > > Do you have an example of such ``'leaf class', i.e. CANNOT be used as
> > > a base class.'' [emphases added]. TIA.

> Allan W wrote:
> > Not speaking for Francis, but... How about any class that implements
> > operator=() this way:
> >
> >     const Foo &operator=(const Foo&f) {
> >        if (this != &f) {
> >           Foo::~Foo();
> >           new(this) Foo(f);
> >        }
> >        return *this;
> >     }
> >
> > NOTE -- I'm not advocating this technique, so please don't tell me how
> > terrible this code is when Foo's constructor can throw, or how it just
> > isn't smart. The point is, this is the only legal way to implement a
> > complete operator= when the class contains a reference or a const member.
> > Furthermore, the C++ standard guarantees that this works, but not if it's
> > a base class -- which means it ought to be marked Final.

petebecker@acm.org (Pete Becker) wrote
> Are you giving this example in order to show how to use final, or to
> show how to abuse it?

Neither, really. I'm Switzerland; I'm neutral (at least on this topic).
I just think it's important to explore it from all angles -- although
lately there's "more heat than light," with some accusations that just
barely made it past the moderator, and so I'm starting to lose interest.

> If final makes this easier to use that's a pretty
> strong argument against final.

How so?

Assume you've inherited this code in a legacy class. The class has a
public data member which is a reference, and this code is being used
to "re-seat" the reference. Fixing the design so that it's safe (and
testing and documenting the change) will take 10 hours for all the
members of the class, and another 800 hours for all the legacy code
that uses it. Living with the problem until the next major version
is free, but potentially error-prone. The "final" keyword (or any
other method to prevent inheritance) would at least diagnose one
potentially obscure error, which is obvious to the class author but
perhaps not to the clients (who, after all, shouldn't be expected
to read the implementation code in order to use the 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: comp.std.c++_2002-12-13@nmhq.net (Niklas Matthies)
Date: Fri, 13 Dec 2002 01:53:51 +0000 (UTC)
Raw View
On 2002-12-10 01:31, Pete Becker <petebecker@acm.org> wrote:
> Francis Glassborow wrote:
>>
>> The only arguments that I would accept against providing 'final' + a
>> mechanism for over-riding it would be that its implementation had
>> serious impact on the semantics of C++.
>
> The final-is-just-like-private folks haven't jumped in to claim that
> being able to override final means we should also be able to override
> private.

We already are able to do that, just not very portably. You can always
manipulate raw memory.

> Could it be that private and final are different when that
> distinction supports a position they like?

It is likely that the desire to override final wouldn't be as rare as
the desire to override private. But that doesn't mean that final is
worthless.

-- Niklas Matthies

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Fri, 13 Dec 2002 05:13:40 +0000 (UTC)
Raw View
Niklas Matthies wrote:
>
> On 2002-12-09 01:18, Pete Becker <petebecker@acm.org> wrote:
> > Niklas Matthies wrote:
> >>
> >> What exactly is the fundamental difference you seem to see, that goes
> >> beyond an arbitrary convention? Continuing to repeat the above like a
> >> mantra doesn't really explain anything.
> >
> > Thank you for asking. You're the first to not just say "you're wrong."
> >
> > You design and implement a class so that it works correctly (modulo
> > errors, of course). You make things private if uncontrolled changes to
> > them will violate your class's invariants, which would violate the
> > assumptions underlying your interface functions.
>
> What if one of those assumptions is that no instance of that class is
> ever the base part of larger object of derived type?

Give an example from real code.

>
> > So you prevent access to those things in order to make sure that your
> > code (the code you wrote to implement the class) works correctly.
> >
> > If someone derives from your class in a way that doesn't make sense that
> > doesn't affect your code. It still works right.
>
> Not necessarily. For a trivial example, place 'assert(typeid(*this) ==
> typeid(my_class));' into some method. For a less trivial example,
> consider a class whose objects always register themselves with some
> facility that only can handle objects with a fixed set of typeids, or
> with a give size, maybe for purposes like garbage collection.

Give an example from real code.

>
> Making a class 'final' specifically means that the author doesn't
> (want to) guarantee that instances of his class will work when they
> occur as a base part of objects of types derived from that class.
>
> I still don't see the crucial difference to the case where the author
> doesn't guarantee that his class will work when client code accesses
> specific members.
>

The difference is that private solves well known problems from actual
experience.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Fri, 13 Dec 2002 16:48:18 +0000 (UTC)
Raw View
Niklas Matthies wrote:
>
> On 2002-12-09 01:19, Pete Becker <petebecker@acm.org> wrote:
> > Yup, that's the bottom line, isn't it? Doesn't what users want; you
> > wrote it, you decide what others can do with it.
>
> Exactly. Do you think it's the language's job to prevent the original
> author from making such decisions? Who is more presumptuous then, the
> author who prevents his class from being derived from, or the language
> that prevents the author from doing so?
>

The language as it stands now doesn't prevent it. How often have you
used this capability?

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kuyper@wizard.net ("James Kuyper Jr.")
Date: Fri, 13 Dec 2002 16:49:24 +0000 (UTC)
Raw View
Pete Becker wrote:
....
> Indeed. If it goes into the language, someone's going to stand up at a
> standards meeting and propose that we go through the standard library
> and mark all the classes that "should" be final.

Of course. Do you want to NOT mark as final, classes that should be
final? You might reasonably argue that they shouldn't be final; you
might reasonably say that there's not a single class in the entire
standard library that should be marked final. You might even argue that
there's not a single class anywhere that should be final. However, it
doesn't make sense to say that there is a class that should be final AND
that it shouldn't be marked as final.


---
[ 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: terekhov@web.de (Alexander Terekhov)
Date: Fri, 13 Dec 2002 16:55:01 +0000 (UTC)
Raw View
Allan W wrote:
[...]
> > >     const Foo &operator=(const Foo&f) {
> > >        if (this != &f) {
> > >           Foo::~Foo();
> > >           new(this) Foo(f);
> > >        }
> > >        return *this;
> > >     }
[...]
> > class Bar : Foo /* ... */ {
> >   Bar& operator=(const Bar&); // unimplemented
> >   /* ... */
> > public:
> >   /* ... */
> > };
>
> Would you say that Bar IS-A Foo?

No.

regards,
alexander.

---
[ 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: terekhov@web.de (Alexander Terekhov)
Date: Fri, 13 Dec 2002 16:55:16 +0000 (UTC)
Raw View
Allan W wrote:

[ ... "class Bar : Foo /* ... */ {" ... ]

> Because Foo objects can be assigned, many people will be surprised
> that Bar objects cannot.

#include <iostream>
using namespace std;

struct Foo {

  Foo() {
    cout << "Foo-ctor(" << this << ")\n";
  }

 ~Foo() throw() {
    cout << "Foo-dtor(" << this << ")\n";
  }

  Foo( const Foo& other ) {
    cout << "Foo-copy-ctor(" << this << ") from " << &other << '\n';
  }

  void swap( Foo& other ) throw() {
    cout << this << " <- Foo swap Foo -> " << &other << '\n';
  }

};

template< class T, int >
class implementation_detail : public T /* ... */ {
  /* ... */
public:

  implementation_detail() /* ... */ { /* ... */ }

  implementation_detail( const implementation_detail& other ) :
    T( other ) /* ... */ { /* ... */ }

  /* ... */
};

class Bar : implementation_detail< Foo, 1 >,
            implementation_detail< Foo, 2 > /* ... */ {
  /* ... */
public:

  Bar() /* ... */ { /* ... */ }

  Bar( const Bar& other ) :
    implementation_detail< Foo, 1 >( other ),
    implementation_detail< Foo, 2 >( other )
    /* ... */ { /* ... */ }

  void swap( Bar& other ) throw() {
    implementation_detail< Foo, 1 >::swap(
      static_cast< implementation_detail< Foo, 1 >& >( other ) );
    implementation_detail< Foo, 2 >::swap(
      static_cast< implementation_detail< Foo, 2 >& >( other ) );
  }

  Bar& operator=( Bar temp ) throw() {
    this->swap( temp );
    return *this;
  }

  /* ... */

};

int main() {
  cout << "-- Bar b1 --\n";
  Bar b1;
  cout << "-- Bar b2 --\n";
  Bar b2;
  cout << "-- b1 = b2 --\n";
  b1 = b2;
  cout << " -- bye-bye --\n";
}

regards,
alexander.

---
[ 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: alain@miniussi.net (Alain Miniussi)
Date: Fri, 13 Dec 2002 19:19:46 +0000 (UTC)
Raw View
Francis Glassborow wrote:

[...]

> I also note that proponents have suggested that 'final' should be
> overridable but only by deliberate action.

But then, wouldn't it  become worthless for optimization ?

Alain

---
[ 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: pdimov@mmltd.net (Peter Dimov)
Date: Fri, 13 Dec 2002 21:24:58 +0000 (UTC)
Raw View
allan_w@my-dejanews.com (Allan W) wrote in message news:<7f2735a5.0212121624.33fa0b81@posting.google.com>...
>
> The real argument in favor of preventing derivation, seems to be that
> not all classes have virtual destructors. Virtual destructors are
> vitally important if the class is used polymorphically, [...]

Not correct.

class X
{
public:

  virtual void f() = 0;

protected:

  ~X() {}
};

class impl: public X
{
public:

  virtual void f() {}
};

boost::shared_ptr<X> px(new impl);

---
[ 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: pdimov@mmltd.net (Peter Dimov)
Date: Fri, 13 Dec 2002 21:25:42 +0000 (UTC)
Raw View
francis.glassborow@ntlworld.com (Francis Glassborow) wrote in message news:<7dLvxgEzrQ+9Ewa2@robinton.demon.co.uk>...
> In article <7dc3b1ea.0212120750.13dc5d4c@posting.google.com>, Peter
> Dimov <pdimov@mmltd.net> writes
> >The point of the above is that I'll have to worry about final classes
> >breaking my libraries, regardless of whether I buy something or not.
>
> Then you should already be worrying. Scott Meyers has maintained for
> nearly a decade that 'in general' deriving from a leaf class (or more
> precisely, any non-abstract class) is a design error. I can remember
> arguing with him on that issue at a SIGS conference in the UK in 1992 or
> 93.

Scott Meyers is right. In general, exposing such a class hierarchy to
users, or expecting them to derive from a non-abstract class
(stronger: any class that has state) can be considered a design error;
there are exceptions - the standard library has several examples.

But I am not talking about interfaces here. I am talking about using
the inheritance tool in a library as an implementation detail.

> Couple that with the already existing mechanisms for preventing
> derivation becoming steadily more widely known and the problem you fear
> is already out of the bag.

I haven't seen any evidence for this claim.

> Final would at least allow you to document that your classes and
> templates will not work with final classes.

I don't see how "final" would help me to write documentation.

---
[ 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: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Sat, 14 Dec 2002 06:28:03 +0000 (UTC)
Raw View
In article <uvk5qokpbknu7a@corp.supernews.com>, Alain Miniussi
<alain@miniussi.net> writes
>Francis Glassborow wrote:
>
>[...]
>
>> I also note that proponents have suggested that 'final' should be
>> overridable but only by deliberate action.
>
>But then, wouldn't it  become worthless for optimization ?

Yes, but I was envisaging that virtuality was killed once and for all,
but that it might still be explicitly allowed to over-rule 'though shalt
not use this as a (non-polymorphic) base.


--
Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ 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: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Sat, 14 Dec 2002 09:49:24 +0000 (UTC)
Raw View
In article <7dc3b1ea.0212130548.620e658b@posting.google.com>, Peter
Dimov <pdimov@mmltd.net> writes
>> Couple that with the already existing mechanisms for preventing
>> derivation becoming steadily more widely known and the problem you fear
>> is already out of the bag.
>
>I haven't seen any evidence for this claim.

Track comp.lang.c++.moderated and you will see the question 'How do I
block inheritance' turning up increasingly often. Then there is the fact
that boost provides the tools. Then there is the fact that as Java is
being used increasingly as an introductory language, average programmers
migrating will want to write C++ as if it were Java.

>
>> Final would at least allow you to document that your classes and
>> templates will not work with final classes.
>
>I don't see how "final" would help me to write documentation.

Simply for example:

This template requires that all its template parameter can be derived
from.

Or when your technical support desk gets a question as to why something
does not work an enquiry about whether the class is marked as final
quickly gives them the answer (currently we can have classes that cannot
be derived from, but it is less straight forward to determine that.)



--
Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ 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: comp.std.c++_2002-12-14@nmhq.net (Niklas Matthies)
Date: Sat, 14 Dec 2002 09:49:36 +0000 (UTC)
Raw View
On 2002-12-13 05:13, Pete Becker <petebecker@acm.org> wrote:
> Niklas Matthies wrote:
>> On 2002-12-09 01:18, Pete Becker <petebecker@acm.org> wrote:
[...]
>> > You design and implement a class so that it works correctly (modulo
>> > errors, of course). You make things private if uncontrolled changes to
>> > them will violate your class's invariants, which would violate the
>> > assumptions underlying your interface functions.
>>
>> What if one of those assumptions is that no instance of that class is
>> ever the base part of larger object of derived type?
>
> Give an example from real code.
>
>> > So you prevent access to those things in order to make sure that your
>> > code (the code you wrote to implement the class) works correctly.
>> >
>> > If someone derives from your class in a way that doesn't make sense that
>> > doesn't affect your code. It still works right.
>>
>> Not necessarily. For a trivial example, place 'assert(typeid(*this) ==
>> typeid(my_class));' into some method. For a less trivial example,
>> consider a class whose objects always register themselves with some
>> facility that only can handle objects with a fixed set of typeids, or
>> with a give size, maybe for purposes like garbage collection.
>
> Give an example from real code.
>
>> Making a class 'final' specifically means that the author doesn't
>> (want to) guarantee that instances of his class will work when they
>> occur as a base part of objects of types derived from that class.
>>
>> I still don't see the crucial difference to the case where the author
>> doesn't guarantee that his class will work when client code accesses
>> specific members.
>
> The difference is that private solves well known problems from actual
> experience.

I see. So the difference actually isn't the one between "my code
works" and "your code works" that you stated previously. Thanks
for clarifying!

-- Niklas Matthies

---
[ 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: comp.std.c++_2002-12-14@nmhq.net (Niklas Matthies)
Date: Sat, 14 Dec 2002 09:49:49 +0000 (UTC)
Raw View
On 2002-12-13 16:48, Pete Becker <petebecker@acm.org> wrote:
> Niklas Matthies wrote:
>>
>> On 2002-12-09 01:19, Pete Becker <petebecker@acm.org> wrote:
>> > Yup, that's the bottom line, isn't it? Doesn't what users want; you
>> > wrote it, you decide what others can do with it.
>>
>> Exactly. Do you think it's the language's job to prevent the original
>> author from making such decisions? Who is more presumptuous then, the
>> author who prevents his class from being derived from, or the language
>> that prevents the author from doing so?
>
> The language as it stands now doesn't prevent it.

It allows to prevent creating instances of a derived class, but
unless I missed something it doesn't prevent derivation per se.

> How often have you used this capability?

I haven't, because it isn't self-documenting.

-- Niklas Matthies

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Sat, 14 Dec 2002 09:50:04 +0000 (UTC)
Raw View
"James Kuyper Jr." wrote:
>
> Pete Becker wrote:
> ....
> > Indeed. If it goes into the language, someone's going to stand up at a
> > standards meeting and propose that we go through the standard library
> > and mark all the classes that "should" be final.
>
> Of course. Do you want to NOT mark as final, classes that should be
> final? You might reasonably argue that they shouldn't be final; you
> might reasonably say that there's not a single class in the entire
> standard library that should be marked final. You might even argue that
> there's not a single class anywhere that should be final. However, it
> doesn't make sense to say that there is a class that should be final AND
> that it shouldn't be marked as final.
>

Sigh. The context, which you snipped, was:

>> francis.glassborow@ntlworld.com (Francis Glassborow) wrote in message
news:<4M2$lbBI2w99Ewit@robinton.demon.co.uk>...
>> > No library designer would be compelled to use final were it available.
>>

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dave@boost-consulting.com (David Abrahams)
Date: Sat, 14 Dec 2002 22:15:21 +0000 (UTC)
Raw View
francis.glassborow@ntlworld.com (Francis Glassborow) writes:

> In article <7dc3b1ea.0212130548.620e658b@posting.google.com>, Peter
> Dimov <pdimov@mmltd.net> writes
>>> Couple that with the already existing mechanisms for preventing
>>> derivation becoming steadily more widely known and the problem you fear
>>> is already out of the bag.
>>
>>I haven't seen any evidence for this claim.
>
> Track comp.lang.c++.moderated and you will see the question 'How do I
> block inheritance' turning up increasingly often. Then there is the
> fact that boost provides the tools.

Which tools?

>>> Final would at least allow you to document that your classes and
>>> templates will not work with final classes.
>>
>>I don't see how "final" would help me to write documentation.
>
> Simply for example:
>
> This template requires that all its template parameter can be derived
> from.

That's possible today, and final didn't help.

> Or when your technical support desk gets a question as to why
> something does not work an enquiry about whether the class is marked
> as final quickly gives them the answer (currently we can have classes
> that cannot be derived from, but it is less straight forward to
> determine that.)

I'm afraid the claim is that these questions will happen much more
often if blocking inheritance is widely available.

--
                       David Abrahams
   dave@boost-consulting.com * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Sat, 14 Dec 2002 22:15:22 +0000 (UTC)
Raw View
Niklas Matthies wrote:
>
> On 2002-12-13 05:13, Pete Becker <petebecker@acm.org> wrote:
> > Niklas Matthies wrote:
> >> On 2002-12-09 01:18, Pete Becker <petebecker@acm.org> wrote:
> [...]
> >> > You design and implement a class so that it works correctly (modulo
> >> > errors, of course). You make things private if uncontrolled changes to
> >> > them will violate your class's invariants, which would violate the
> >> > assumptions underlying your interface functions.
> >>
> >> What if one of those assumptions is that no instance of that class is
> >> ever the base part of larger object of derived type?
> >
> > Give an example from real code.
> >
> >> > So you prevent access to those things in order to make sure that your
> >> > code (the code you wrote to implement the class) works correctly.
> >> >
> >> > If someone derives from your class in a way that doesn't make sense that
> >> > doesn't affect your code. It still works right.
> >>
> >> Not necessarily. For a trivial example, place 'assert(typeid(*this) ==
> >> typeid(my_class));' into some method. For a less trivial example,
> >> consider a class whose objects always register themselves with some
> >> facility that only can handle objects with a fixed set of typeids, or
> >> with a give size, maybe for purposes like garbage collection.
> >
> > Give an example from real code.
> >
> >> Making a class 'final' specifically means that the author doesn't
> >> (want to) guarantee that instances of his class will work when they
> >> occur as a base part of objects of types derived from that class.
> >>
> >> I still don't see the crucial difference to the case where the author
> >> doesn't guarantee that his class will work when client code accesses
> >> specific members.
> >
> > The difference is that private solves well known problems from actual
> > experience.
>
> I see. So the difference actually isn't the one between "my code
> works" and "your code works" that you stated previously. Thanks
> for clarifying!

I never said that the difference was between "my code works" and "your
code works." Thanks for misrepresenting.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Sun, 15 Dec 2002 00:28:56 +0000 (UTC)
Raw View
In article <uznr8y7tz.fsf@boost-consulting.com>, David Abrahams
<dave@boost-consulting.com> writes
>> Or when your technical support desk gets a question as to why
>> something does not work an enquiry about whether the class is marked
>> as final quickly gives them the answer (currently we can have classes
>> that cannot be derived from, but it is less straight forward to
>> determine that.)
>
>I'm afraid the claim is that these questions will happen much more
>often if blocking inheritance is widely available.

It is widely available already. Stopping abuse is a matter of education
not prohibiting simplification.

--
Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ 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: dave@boost-consulting.com (David Abrahams)
Date: Sun, 15 Dec 2002 22:15:37 +0000 (UTC)
Raw View
francis.glassborow@ntlworld.com (Francis Glassborow) writes:

> In article <uznr8y7tz.fsf@boost-consulting.com>, David Abrahams
> <dave@boost-consulting.com> writes
>>> Or when your technical support desk gets a question as to why
>>> something does not work an enquiry about whether the class is marked
>>> as final quickly gives them the answer (currently we can have classes
>>> that cannot be derived from, but it is less straight forward to
>>> determine that.)
>>
>>I'm afraid the claim is that these questions will happen much more
>>often if blocking inheritance is widely available.
>
> It is widely available already. Stopping abuse is a matter of
> education not prohibiting simplification.

Let's not mince words, eh?  Accessibility is largely proportional to
simplicity and directness of expression.  I know that anybody who
wants to /can/ use the virtual base hack, but many people don't want
to because it's indirect and (like new-style casts) ugly, not to
mention that it comes with some efficiency costs.  If you make it
simple and accessible it will be used (and abused) more.

C++ is full of dangers, but mistaken derivation doesn't rate high on
the list.  IMO we have much bigger fish to fry in the project of
making C++ easy to use correctly and hard to misuse.

BTW #1, has anybody tried to write a thorough characterization of
which kinds of classes would be good candidates for marking as
'final'?

BTW #2, has anybody considered that non-member functions might have an
effect on these criteria?

BTW #3, Francis, you didn't answer my other questions.

--
                       David Abrahams
   dave@boost-consulting.com * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution

---
[ 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: scottm@toast.net ("Scott Mayo")
Date: Sun, 15 Dec 2002 22:21:48 +0000 (UTC)
Raw View
"Alain Miniussi" <alain@miniussi.net> wrote in message
news:uvk5qokpbknu7a@corp.supernews.com...
> Francis Glassborow wrote:

> > I also note that proponents have suggested that 'final' should be
> > overridable but only by deliberate action.

> But then, wouldn't it  become worthless for optimization ?

Yes. 'final' must not be overridable. The whole point is to make
it clear that inheritance will not occur. If it can occur anyway,
it's meaningless.




---
[ 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: scottm@toast.net ("Scott Mayo")
Date: Sun, 15 Dec 2002 22:24:12 +0000 (UTC)
Raw View
> Could someone please provide a summary of the general view of the pro
> group. What is "final"? What kinds of inheritance does it block? Which
> standard library classes should be marked "final"? When should "final"
> be used?

final (as I see it) would look like Java's final. It would serve as notice
that a class may not be inherited from (no is-a usage at all) and it would
allow possible optimizations of the code. It might be used to indicate
that the class is not written in a way that makes general derivation
safe; it might indicate that this is my code not your code, and I don't
want you extending it because you haven't arranged for that right with me,
or it might see use when every possible optimization is needed. The latter
is the main justification for it in Java.

I don't know of a hue and cry against 'final' in Java, though I suppose
opponents could claim this is because final is so necessary (Java
performs hideously without it) that it has ceased to be seen as evil.

In summary, 'final' is cheap to implement, has prior art in Java, and
represents a clear way to specify something that can be specified
now, but using idioms which are obscure (maybe not to people
here, but to many C++ programmers who are not language wonks.)
Admittedly, huge numbers of programmers wouldn't use it, the
same way that lots of programmers don't mess with const and private
today, but the ones that would, probably would have sound reasons
for it.

I also see some advantages in code linting. "Class is not final;
destructor is not virtual.. does this class support inheritance?"
could make people think through designs more carefully in
early stages of development. Heaven knows C++ has enough
subtle snares to make such checks valuable.

As far as I can make out, the argument against it is that someone
might deliberately make a class impossible to inherit from, when
they shouldn't have. But they can do that anyway, with obscure
tricks. Given that final has value as an optimization AND as a
way to warn people off of making gruesome mistakes, and given
that it's already possible to sabotage inheritance (in ugly ways),
it's hard for me to see objections.

People who write perfect classes that are always perfectly
extensible will never need it. For the rest of us, I see
advantages.



---
[ 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: Pete Becker <petebecker@acm.org>
Date: Sun, 15 Dec 2002 19:05:54 CST
Raw View
Scott Mayo wrote:
>
> I don't know of a hue and cry against 'final' in Java, though I suppose
> opponents could claim this is because final is so necessary (Java
> performs hideously without it) that it has ceased to be seen as evil.
>

Java isn't C++. There are many things that Java has done that we
shouldn't emulate in C++.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: rmaddox@isicns.com (Randy Maddox)
Date: Mon, 16 Dec 2002 19:10:33 +0000 (UTC)
Raw View
Pete Becker <petebecker@acm.org> wrote in message news:<3DFD127A.DAEBC78@acm.org>...
> Scott Mayo wrote:
> >
> > I don't know of a hue and cry against 'final' in Java, though I suppose
> > opponents could claim this is because final is so necessary (Java
> > performs hideously without it) that it has ceased to be seen as evil.
> >
>
> Java isn't C++. There are many things that Java has done that we
> shouldn't emulate in C++.
>
> --
>
> Pete Becker
> Dinkumware, Ltd. (http://www.dinkumware.com)
>

If you had not clipped so much of the context it would have been clear
that Scott Mayo was not suggesting that C++ emulate Java, but rather
citing Java as an example of prior art in the use of the 'final'
concept.  In particular note the restored context here:

"In summary, 'final' is cheap to implement, has prior art in Java, and
represents a clear way to specify something that can be specified
now, but using idioms which are obscure (maybe not to people
here, but to many C++ programmers who are not language wonks.)"

Randy.

---
[ 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: alain@miniussi.net (Alain Miniussi)
Date: Mon, 16 Dec 2002 20:20:15 +0000 (UTC)
Raw View
Francis Glassborow wrote:

> In article <uvk5qokpbknu7a@corp.supernews.com>, Alain Miniussi
> <alain@miniussi.net> writes
>>Francis Glassborow wrote:
>>
>>[...]
>>
>>> I also note that proponents have suggested that 'final' should be
>>> overridable but only by deliberate action.
>>
>>But then, wouldn't it  become worthless for optimization ?
>
> Yes, but I was envisaging that virtuality was killed once and for all,
> but that it might still be explicitly allowed to over-rule 'though shalt
> not use this as a (non-polymorphic) base.

In implementation words: "do not touch the vtable". ?

Alain


---
[ 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: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Mon, 16 Dec 2002 21:31:23 +0000 (UTC)
Raw View
In article <u65tvvs5z.fsf@boost-consulting.com>, David Abrahams
<dave@boost-consulting.com> writes
>C++ is full of dangers, but mistaken derivation doesn't rate high on
>the list.  IMO we have much bigger fish to fry in the project of
>making C++ easy to use correctly and hard to misuse.
>
>BTW #1, has anybody tried to write a thorough characterization of
>which kinds of classes would be good candidates for marking as
>'final'?
>
>BTW #2, has anybody considered that non-member functions might have an
>effect on these criteria?
>
>BTW #3, Francis, you didn't answer my other questions.

Largely because until the participants decide to discuss the issues
rather than just say 'over my dead body' there does not seem much point.

Everyone here knows it can be done, and, I think that it can easily be
done without serious knock-on effects to the rest of C++. So I find it
interesting to note that almost all of a very long thread has been
largely concerned with political issues rather than technical ones.

As long as we have loud voices raised saying 'do not dream of going
there' it seems unlikely that we will have any serious discussion about
why we should want to.


--
Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ 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: kanze@gabi-soft.de (James Kanze)
Date: Mon, 16 Dec 2002 21:31:32 +0000 (UTC)
Raw View
Pete Becker <petebecker@acm.org> wrote in message
news:<3DFD127A.DAEBC78@acm.org>...
> Scott Mayo wrote:

> > I don't know of a hue and cry against 'final' in Java, though I
> > suppose opponents could claim this is because final is so necessary
> > (Java performs hideously without it) that it has ceased to be seen
> > as evil.

> Java isn't C++. There are many things that Java has done that we
> shouldn't emulate in C++.

Java needs final for protection.  The only way to offer friendship in
Java is by using package access.  And a derived class, even from another
package, can access members with package access.  The result is that for
the "friendship" to be safe, you must be able to 1) seal a package, and
2) prevent inheritance.

I think Dave Harris hit the nail on the head when he spoke about
preventing overriding of functions.  Normally, the only danger to my
code when you inherit from my class is that you override some of the
virtual functions, but not all, and that the virtual functions work
together to ensure class invariants.

I'm just curious, but would there be less resistance if the suggestion
was to introduce "final" for functions, and that if it were applied to a
class, all it meant was that all of the functions were final -- that is,
that you could still inherit from the class, but that you could not
override any virtual function in it?  This would still allow all of the
tricky stuff, I think, but would solve the problem for people wanting to
write robust code.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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: kanze@gabi-soft.de (James Kanze)
Date: Mon, 16 Dec 2002 21:31:48 +0000 (UTC)
Raw View
dave@boost-consulting.com (David Abrahams) wrote in message
news:<u65tvvs5z.fsf@boost-consulting.com>...

   [...]
> BTW #1, has anybody tried to write a thorough characterization of
> which kinds of classes would be good candidates for marking as
> 'final'?

Before this discussion, I would have said just about any value oriented
class.  Having now heard about the special uses of derivation in some
fancy templates, I'll take a second go at it.

The critical point for robustness is to maintain class invariants.
Maintaining class invariants often requires a set of functions which
work together.  A class which derives from my class, and overrides one
of these functions, breaks my code by breaking the class invariants.

If this is the problem "final" is designed to solve (and I think that it
is definitly a problem that final could help solve), then for starters,
you don't need final unless there are virtual functions.  The typical
use of final would be on the concrete class which implements an
interface, to prevent someone from further deriving AND overriding some
of its virtual functions.  (Theoretically, at least, there could also be
issues concerning protected data members in the base class.
Practically, I think that this is rare enough in well designed code that
we can ignore it.  At any rate, they are rare enough in my own code that
I'm not going to worry about it.)

> BTW #2, has anybody considered that non-member functions might have an
> effect on these criteria?

Since non member functions can't be virtual, they can't very well have
an effect on the above criteria, can they.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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: alain@miniussi.net (Alain Miniussi)
Date: Mon, 16 Dec 2002 21:55:43 +0000 (UTC)
Raw View
Pete Becker wrote:

> Scott Mayo wrote:
>>
>> I don't know of a hue and cry against 'final' in Java, though I suppose
>> opponents could claim this is because final is so necessary (Java
>> performs hideously without it) that it has ceased to be seen as evil.
>>
>
> Java isn't C++. There are many things that Java has done that we
> shouldn't emulate in C++.

How do you fix the perf issue in C++ ? The only solution
I can think of (without final) implies global optimization
and no dynamic linking.

Alain


---
[ 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: dave@boost-consulting.com (David Abrahams)
Date: Mon, 16 Dec 2002 23:08:21 +0000 (UTC)
Raw View
kanze@gabi-soft.de (James Kanze) writes:

> dave@boost-consulting.com (David Abrahams) wrote in message
> news:<u65tvvs5z.fsf@boost-consulting.com>...
>
>    [...]
>> BTW #1, has anybody tried to write a thorough characterization of
>> which kinds of classes would be good candidates for marking as
>> 'final'?
>
> Before this discussion, I would have said just about any value oriented
> class.  Having now heard about the special uses of derivation in some
> fancy templates, I'll take a second go at it.
>
> The critical point for robustness is to maintain class invariants.
> Maintaining class invariants often requires a set of functions which
> work together.  A class which derives from my class, and overrides one
> of these functions, breaks my code by breaking the class invariants.
>
> If this is the problem "final" is designed to solve (and I think that it
> is definitly a problem that final could help solve), then for starters,
> you don't need final unless there are virtual functions.  The typical
> use of final would be on the concrete class which implements an
> interface, to prevent someone from further deriving AND overriding some
> of its virtual functions.

That's not bad.  I can certainly imagine wanting to prevent virtual
functions from being overridden again, either selectively or in bulk.
It certainly sounds like a different "final" than people have been
asking for so far, though.

> (Theoretically, at least, there could also be
> issues concerning protected data members in the base class.
> Practically, I think that this is rare enough in well designed code that
> we can ignore it.  At any rate, they are rare enough in my own code that
> I'm not going to worry about it.)
>
>> BTW #2, has anybody considered that non-member functions might have an
>> effect on these criteria?
>
> Since non member functions can't be virtual, they can't very well have
> an effect on the above criteria, can they.

Nope.  Some mention had be made of problems with slicing off base
classes (swap was one example), and that particular issue is not
limited to member functions.

--
                       David Abrahams
   dave@boost-consulting.com * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution

---
[ 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: Mon, 16 Dec 2002 23:08:28 +0000 (UTC)
Raw View
Alain Miniussi wrote:
> How do you fix the perf issue in C++ ?

By not making the methods virtual in the first place.

---
[ 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: brangdon@cix.co.uk (Dave Harris)
Date: Mon, 16 Dec 2002 23:10:08 +0000 (UTC)
Raw View
kanze@gabi-soft.de (James Kanze) wrote (abridged):
> I'm just curious, but would there be less resistance if the suggestion
> was to introduce "final" for functions, and that if it were applied to a
> class, all it meant was that all of the functions were final -- that is,
> that you could still inherit from the class, but that you could not
> override any virtual function in it?  This would still allow all of the
> tricky stuff, I think, but would solve the problem for people wanting to
> write robust code.

Another variation would be to allow final inheritance:

    class Base {
    public:
        int call_method() {
            return method();
        }
    private:
        virtual int method() {
            return 0;
        }
    };

    class Derived: private final Base { // New syntax.
    public:
         int test() {  // Returns 0.
             return Base::call_method();
         }
    private:
        int method() { // Not virtual!
            return 1;
        }
    };

The idea being for Derived to avoid accidentally overriding virtual
methods of Base. A call to Derived::test() would call Base::call_method(),
which would call Base::method(), not Derived::method().

This would make inheritance safer. Now I can inherit from you without
accidentally screwing up your class invariant. It would remove one of the
objections to inheriting privately from standard classes.

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."

---
[ 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: nid_oizo@yahoo.com_removethe_ (Nicolas Fleury)
Date: Mon, 16 Dec 2002 23:10:39 +0000 (UTC)
Raw View
James Kanze wrote:
> I think Dave Harris hit the nail on the head when he spoke about
> preventing overriding of functions.  Normally, the only danger to my
> code when you inherit from my class is that you override some of the
> virtual functions, but not all, and that the virtual functions work
> together to ensure class invariants.
>
> I'm just curious, but would there be less resistance if the suggestion
> was to introduce "final" for functions, and that if it were applied to a
> class, all it meant was that all of the functions were final -- that is,
> that you could still inherit from the class, but that you could not
> override any virtual function in it?  This would still allow all of the
> tricky stuff, I think, but would solve the problem for people wanting to
> write robust code.

Personnally, I like this idea.  Maybe it could be more orthogonal with
the rest of C++ to have it only for member functions.  Would a final
destructor mean a final class?  Yes and no.  The only safe way to
inherit from it would be in private inheritance as workaround to have a
private member initialized before a base class.  You would also
typically get a compiler warning when inheriting publicly from a class
with a final destructor as mine give me one when inheriting from a class
with non-virtual destructor.

This way, finality provides some optimizations without forbidding
inheritance.  Classes developers have then the choice to decide when
member functions virtualities start *and* stop.

Regards,

Nicolas Fleury

---
[ 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: tknox@flytechnology.com (Timothy Knox)
Date: Mon, 16 Dec 2002 23:14:43 +0000 (UTC)
Raw View
Somewhere on Basilisk Station, on Sunday December 15 2002 16.24, The
Honorable Scott Mayo wrote:

<snip>
> I also see some advantages in code linting. "Class is not final;
> destructor is not virtual.. does this class support inheritance?"
> could make people think through designs more carefully in
> early stages of development. Heaven knows C++ has enough
> subtle snares to make such checks valuable.
>
<snip>

First, the disclaimer: I am NOT a C++ guru. :) However, it seems to me that
if you declare any methods in your class virtual, you are already
implicitly saying that you expect your class to support derivation, and
that that would be sufficient to trigger the "destructor is not virtual"
warning.

--
Timothy Knox
#include <std/disclaimer.h>
"There are some people who think all black people look
alike. We call those people cops." -- Dave Chappelle

---
[ 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: alain@miniussi.net (Alain Miniussi)
Date: Mon, 16 Dec 2002 23:44:05 +0000 (UTC)
Raw View
Hyman Rosen wrote:

> Alain Miniussi wrote:
>> How do you fix the perf issue in C++ ?
>
> By not making the methods virtual in the first place.

That's not the case I'm talking about.

My method *is* virtual in some base class, in some
derived, probably leaf, class, I want to stop that.
I can do that in Java, how do I do that in C++ ?

As an example, consider the Visitor design pattern,
In the body of a Visitor function, I have no reason to
pay the price of a virtual call when invoquing a method
on the visited object. Doing such optimization by hand,
and I have seen such evil, is likely to fail at
some point.

Alain

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Tue, 17 Dec 2002 00:38:10 +0000 (UTC)
Raw View
Alain Miniussi wrote:
>
> Pete Becker wrote:
>
> > Scott Mayo wrote:
> >>
> >> I don't know of a hue and cry against 'final' in Java, though I suppose
> >> opponents could claim this is because final is so necessary (Java
> >> performs hideously without it) that it has ceased to be seen as evil.
> >>
> >
> > Java isn't C++. There are many things that Java has done that we
> > shouldn't emulate in C++.
>
> How do you fix the perf issue in C++ ?

You'll have to say more about what you think the perf (is that
"performance"?) issue is. Last I looked, people weren't complaining that
C++ code was just too slow.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Tue, 17 Dec 2002 02:19:22 +0000 (UTC)
Raw View
Alain Miniussi wrote:
>
> As an example, consider the Visitor design pattern,
> In the body of a Visitor function, I have no reason to
> pay the price of a virtual call when invoquing a method
> on the visited object.

And how high is the price of a virtual call? Have you determined that
virtual calls are a bottleneck in your program?

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Tue, 17 Dec 2002 02:19:49 +0000 (UTC)
Raw View
Randy Maddox wrote:
>
> Pete Becker <petebecker@acm.org> wrote in message news:<3DFD127A.DAEBC78@acm.org>...
> > Scott Mayo wrote:
> > >
> > > I don't know of a hue and cry against 'final' in Java, though I suppose
> > > opponents could claim this is because final is so necessary (Java
> > > performs hideously without it) that it has ceased to be seen as evil.
> > >
> >
> > Java isn't C++. There are many things that Java has done that we
> > shouldn't emulate in C++.
> >
> If you had not clipped so much of the context it would have been clear
> that Scott Mayo was not suggesting that C++ emulate Java, but rather
> citing Java as an example of prior art in the use of the 'final'
> concept.  In particular note the restored context here:
>
> "In summary, 'final' is cheap to implement, has prior art in Java, and
> represents a clear way to specify something that can be specified
> now, but using idioms which are obscure (maybe not to people
> here, but to many C++ programmers who are not language wonks.)"
>

Java practices are not prior art for C++, although they might be
considered prior graffiti. Java is a different language with different
design goals and a different runtime environment. Even if final is good
in Java that doesn't say anything about its utility in C++.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: allan_w@my-dejanews.com (Allan W)
Date: Tue, 17 Dec 2002 02:20:33 +0000 (UTC)
Raw View
pdimov@mmltd.net (Peter Dimov) wrote
> francis.glassborow@ntlworld.com (Francis Glassborow) wrote
> > Final would at least allow you to document that your classes and
> > templates will not work with final classes.
>
> I don't see how "final" would help me to write documentation.

Please allow me to demonstrate. Here's the version without final:

    struct shape {
        ~shape()=0;
        void draw() = 0;
        // ... etc ...
    };
    shape::~shape() {};

    struct circle : public shape { // Do not derive from this class!
        circle(double center_x, center_y, radius);
        ~circle() {}
        void draw(); // Defined elsewhere
    };

    struct square : public shape { // Do not derive from this class!
        square(double left, double top, double width, double height);
        ~square() {}
        void draw(); // Defined elsewhere
    };

    // Note: NOT part of shape heirarchy
    struct shapeless_blob { // Do not derive from this class!
        shapeless_blob();
        ~shapeless_blob() {}
        void draw(); // Defined elsewhere
    };

With the documentation of "final", this becomes much simpler:
    struct shape {
        ~shape()=0;
        void draw() = 0;
        // ... etc ...
    };
    shape::~shape() {};

    struct circle : public shape { // final!
        circle(double center_x, center_y, radius);
        ~circle() {}
        void draw(); // Defined elsewhere
    };

    struct square : public shape { // final!
        square(double left, double top, double width, double height);
        ~square() {}
        void draw(); // Defined elsewhere
    };

    // Note: NOT part of shape heirarchy
    struct shapeless_blob { // final
        shapeless_blob();
        ~shapeless_blob() {}
        void draw(); // Defined elsewhere
    };

We still need (in-source) documentation -- but now it's MUCH easier
to read. See how much better?   8-)

---
[ 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: Tue, 17 Dec 2002 02:20:45 +0000 (UTC)
Raw View
Alain Miniussi wrote:
 > Doing such optimization by hand,
> and I have seen such evil, is likely to fail at
> some point.

You mean this: p->Derived::f() ?

---
[ 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: kuyper@wizard.net ("James Kuyper Jr.")
Date: Tue, 17 Dec 2002 03:42:05 +0000 (UTC)
Raw View
Pete Becker wrote:
....
> Java practices are not prior art for C++, although they might be
> considered prior graffiti. Java is a different language with different
> design goals and a different runtime environment.  ...

Yes, some of those differences are very significant, in certain
circumstances. And in others, they're completely insignificant. The fact
that those differences exist is not sufficient in itself to justify
rejecting prior art from Java.

> ... Even if final is good
> in Java that doesn't say anything about its utility in C++.

That depends entirely upon why it's good. Several people have already
explained Java-specific reasons why Java needs 'final'. But 'final' is
also wanted for other reasons, and the fact that Java is different from
C++ isn't sufficient to guarantee that those reasons don't apply to C++.
If they don't apply, the appropriate argument is to explain why; don't
pretend that Java is a completely unrelated language; anyone who knows
both languages will know that you're exaggerating for effect.

And even if it Java were a completely unrelated language - 'prior art'
doesn't have to be in the same language, or even in a similar one.
"Same", or at least "similar", certainly helps. However, even a
completely unrelated language can have a feature that would be a good
idea to add to C++; and the experience with that feature in that
language has some (limited) value in judging whether it would be
feasible and useful to add to C++.

---
[ 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: belvis@pacbell.net (Bob Bell)
Date: Tue, 17 Dec 2002 06:19:15 +0000 (UTC)
Raw View
alain@miniussi.net (Alain Miniussi) wrote in message news:<uvsp6c6n5p6n46@corp.supernews.com>...
> Hyman Rosen wrote:
>
> > Alain Miniussi wrote:
> >> How do you fix the perf issue in C++ ?
> >
> > By not making the methods virtual in the first place.
>
> That's not the case I'm talking about.
>
> My method *is* virtual in some base class, in some
> derived, probably leaf, class, I want to stop that.
> I can do that in Java, how do I do that in C++ ?

Do you know that this is really a problem? How important are the
optimizations that final makes possible?

> As an example, consider the Visitor design pattern,
> In the body of a Visitor function, I have no reason to
> pay the price of a virtual call when invoquing a method
> on the visited object.

It seems to me that if you don't need the virtual call, then you
probably don't need the function to be virtual in the first place.

Perhaps you can describe a little more what kind of scenario you're
imagining?

Bob Bell

---
[ 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: llewelly.@@xmission.dot.com (llewelly)
Date: Tue, 17 Dec 2002 18:07:00 +0000 (UTC)
Raw View
kanze@gabi-soft.de (James Kanze) writes:

> dave@boost-consulting.com (David Abrahams) wrote in message
> news:<u65tvvs5z.fsf@boost-consulting.com>...
>
>    [...]
> > BTW #1, has anybody tried to write a thorough characterization of
> > which kinds of classes would be good candidates for marking as
> > 'final'?
>
> Before this discussion, I would have said just about any value oriented
> class.  Having now heard about the special uses of derivation in some
> fancy templates, I'll take a second go at it.
>
> The critical point for robustness is to maintain class invariants.
> Maintaining class invariants often requires a set of functions which
> work together.  A class which derives from my class, and overrides one
> of these functions, breaks my code by breaking the class invariants.
>
> If this is the problem "final" is designed to solve (and I think that it
> is definitly a problem that final could help solve), then for starters,
> you don't need final unless there are virtual functions.  The typical
> use of final would be on the concrete class which implements an
> interface, to prevent someone from further deriving AND overriding some
> of its virtual functions.  (Theoretically, at least, there could also be
> issues concerning protected data members in the base class.
> Practically, I think that this is rare enough in well designed code that
> we can ignore it.  At any rate, they are rare enough in my own code that
> I'm not going to worry about it.)
[snip]

Your mention of using a 'final'-like feature to preserve class
    invariants is the first I've heard of it. I'm going out on limb
    here, but I strongly suspect most of those supporting final have
    not thought of preserving class invariants, and are trying to
    solve a quite different problem, which your suggestion does not
    address. (I agree that the problem you describe is real, and could
    be solved by the mechanism you suggest - I just think most of the
    other posters here are not thinking about it when they think of
    'final'.)

By use of such things as non-virtual destructors, assignment
    operators, swap members, cast operators, etc, it is possible to
    create a class (call it Base) such that a class Derived which is
    derived from Base has some error-prone behavior when used
    polymorphicly. The classic example is deleteing an object with a
    non-virtual destructor, using a pointer that is not of the
    object's exact type. I believe these kinds of classes are in fact
    the primary bone of contention between the want-finals and the
    not-want-finals.

Those who do not want final insist they can write classes with
    non-virtual destructors, etc, which can be safely derived from, and
    fulfill important needs. They will insist one can derive safely
    from these clases, and they will insist one can use them
    safely. If you look over the boost source code - you will see they
    are correct to insist these things can be done safely and
    usefuly. If you read the appropriate literature - you will see why
    they think all 'good programmers' should know how to use these
    constructs.

Those who want final insist base classes with non-virtual destructors,
    assignment operators, ill-designed cast operators, etc, are an
    important source of errors; they believe that many programmers do
    not read the literature which tells them how to make such things
    as bases with non-virtual destructors safe and useful, they
    believe that not everyone remembers everything they read, and
    finally that programmers are failible human beings, who might
    benefit from additional error checking.

The problem is that both sides, as far as I can see - are correct. Yes,
    inheritance can be misused, and a sanity check on inheritance can
    prevent real errors. And yes, it would be all too easy for a
    misused sanity check to prevent the use of vital inheritance-based
    idioms.



---
[ 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: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: Tue, 17 Dec 2002 18:08:29 +0000 (UTC)
Raw View
pdimov@mmltd.net (Peter Dimov) writes:
>francis.glassborow@ntlworld.com (Francis Glassborow) wrote:
>> Peter Dimov <pdimov@mmltd.net> writes
>> >In the absence of documentation explicitly saying "though shalt not
>> >derive", derivation from a class is perfectly legal, and not a bug.
>> >You must not diagnose it. How many of your classes make that claim in
>> >their documentation? My guess is that none do, and this is exactly as
>> >it should be, since derivation is not a mistake by itself.
>>
>> And that is exactly what Fergus et al. have been challenging. Sometimes
>> derivation can be a mistake by itself because the class
>> designer/implementor knows that the class needs to make assumptions
>> about pointers and references that would be broken if they happened to
>> point/refer to an instance of a derived type.
>
>Not correct. Derivation is almost never a mistake in itself, and the
>posted example did not demonstrate a case where it is a mistake. The
>swap member function would always work as intended. In some cases it
>would leave a derived class in an inconsistent state, but the meaning
>of "inconsistent" is defined by the design of the derived class and
>not by the fact that it has been derived.

Your statement "The swap member function would always work as intended"
is wrong.  The "swap" member function would not work as intended if
passed an object of a derived class with additional data members.  The
intended meaning of "swap" is that it swap the values of the two objects.
If passed an object of the derived class, it does not have that effect.

However, you're right that it's not the derivation alone that causes the
problem; it's derivation, plus passing a derived class object to the
swap member function, and then relying on the post-condition of the
swap member function.

Clearly it must be OK to rely on the post-condition of a function that
you've called.  All of our programming relies on that.  So that only
leaves two things which could be wrong: the derivation, or passing
the derived class object to the swap member function.

The original poster proposed three uses of "final":
 (1) on classes, to prevent derivation
 (2) on methods, to prevent overriding in derived classes
 (3) on pointers, to prevent pointing to a derived class
     (and likewise for references)

Discussion so far has focussed on the first, which provides the
simplest means of avoiding the problem. But the others may provide
slightly more flexible means to avoid the problem.  In particular,
using (3) on the parameters of the swap member function would allow
derivation, but prevent attempts to violate the pre-condition of the
swap member function.

Unfortunately with C++ syntax there would be a syntactic ambiguity
with "final" on a method -- it could mean either (2) for the method,
or it could mean (3) for the method's "this" pointer.

--
Fergus Henderson <fjh@cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.

---
[ 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: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: Tue, 17 Dec 2002 18:08:48 +0000 (UTC)
Raw View
pdimov@mmltd.net (Peter Dimov) writes:

 >allan_w@my-dejanews.com (Allan W) wrote in message news:<7f2735a5.0212121624.33fa0b81@posting.google.com>...
 >>
 >> The real argument in favor of preventing derivation, seems to be that
 >> not all classes have virtual destructors. Virtual destructors are
 >> vitally important if the class is used polymorphically, [...]
 >
 >Not correct.
 >
 >class X
 >{
 >public:
 >
 >  virtual void f() = 0;
 >
 >protected:
 >
 >  ~X() {}
 >};
 >
 >class impl: public X
 >{
 >public:
 >
 >  virtual void f() {}
 >};
 >
 >boost::shared_ptr<X> px(new impl);

I don't understand.  Won't that result in undefined behaviour
when px's destructor is called?

See 5.3.5 paragraph 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.

--
Fergus Henderson <fjh@cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.

---
[ 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: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Tue, 17 Dec 2002 18:10:20 +0000 (UTC)
Raw View
In article <3DFE7645.DA05A56E@acm.org>, Pete Becker <petebecker@acm.org>
writes
>Java practices are not prior art for C++, although they might be
>considered prior graffiti. Java is a different language with different
>design goals and a different runtime environment. Even if final is good
>in Java that doesn't say anything about its utility in C++.

But WG21 frequently considered that what had been done in other
languages was prior art. You may disagree that that is a correct view of
prior art,  but it is your opinion rather than fact.

--
Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ 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: andersjm@dancontrol.dk ("Anders J. Munch")
Date: Tue, 17 Dec 2002 18:10:48 +0000 (UTC)
Raw View
"James Kanze" <kanze@gabi-soft.de> wrote:
> I'm just curious, but would there be less resistance if the suggestion
> was to introduce "final" for functions, and that if it were applied to a
> class, all it meant was that all of the functions were final -- that is,
> that you could still inherit from the class, but that you could not
> override any virtual function in it?  This would still allow all of the
> tricky stuff, I think, but would solve the problem for people wanting to
> write robust code.

That might be a good political compromise, but it has its downsides:
* It's a more complicated rule - harder to explain.
* Less static analysis is made possible if access to protected members
  is not restricted.  Invariants that could have been guaranteed by
  prohibiting inheritance might be toppled by modifying or calling
  protected members in a subclass.
* It's the less restrictive alternative.  The more restrictive
  alternative can always be relaxed later, but the other way around
  begets legacy issues.

- Anders

--
Anders Munch. Software Engineer, Dancontrol A/S, Haderslev, Denmark
Still confused but at a higher level.


---
[ 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: andersjm@dancontrol.dk ("Anders J. Munch")
Date: Tue, 17 Dec 2002 18:11:15 +0000 (UTC)
Raw View
"David Abrahams" <dave@boost-consulting.com> wrote:
>
> BTW #1, has anybody tried to write a thorough characterization of
> which kinds of classes would be good candidates for marking as
> 'final'?

Speaking for myself: I would mark as final any class that is intended
for instantiation.  That would be, like, 80% of my classes?  (At least
- I would have given a more accurate number, but "grep 'final class'"
doesn't tell me anything useful - yet.)

Whenever encountering problems because final prevents me from doing
something useful, I would do the appropriate refactoring - which could
be as simple as removing the 'final' keyword.  A typical refactoring
would also rename the class and derive a new final class from it with
the old name.  This is no different from what I do today, only the
improved compiler diagnostics would make it easier.

Library authors whose customers have no access to the source are in a
very different position from me, and will probably use final scarcely
or never.

- Anders

--
Anders Munch. Software Engineer, Dancontrol A/S, Haderslev, Denmark
Still confused but at a higher level.


---
[ 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: petebecker@acm.org (Pete Becker)
Date: Tue, 17 Dec 2002 18:11:40 +0000 (UTC)
Raw View
"James Kuyper Jr." wrote:
>
> Pete Becker wrote:
> ....
> > Java practices are not prior art for C++, although they might be
> > considered prior graffiti. Java is a different language with different
> > design goals and a different runtime environment.  ...
>
> Yes, some of those differences are very significant, in certain
> circumstances. And in others, they're completely insignificant. The fact
> that those differences exist is not sufficient in itself to justify
> rejecting prior art from Java.

Nope. But it requires far more detailed analysis than merely reciting
that Java has some feature.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dave@boost-consulting.com (David Abrahams)
Date: Wed, 11 Dec 2002 18:52:02 +0000 (UTC)
Raw View
francis.glassborow@ntlworld.com (Francis Glassborow) writes:

> By the way, there seems to be confusion in some peoples minds as to
> what this is being applied to. I am not interested in finalisation of
> virtual methods and finalisation of virtual bases is both confusing
> and not a feature that could be tried and then removed (without
> cost). What I am in favour of (and I think quite a few others are) is
> the ability to declare that a class is a 'leaf class', i.e. cannot be
> used as a base class.

If we do get this, I sure hope that we don't get it before some
standard built-in support for type traits. At least one important type
trait implementation depends on being able to declare a class derived
from its argument.

--
                       David Abrahams
   dave@boost-consulting.com * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution

---
[ 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: nid_oizo@yahoo.com_removethe_ (Nicolas Fleury)
Date: Wed, 11 Dec 2002 19:31:32 +0000 (UTC)
Raw View
Gabriel Dos Reis wrote:
> nid_oizo@yahoo.com_removethe_ (Nicolas Fleury) writes:
>
> [...]
>
> | C++ is a language that provides many features to detect errors at
> | compile-time instead of at run-time.  A final-like feature seems to me
> | suitable for C++.
>
> I think that argument can be made for *any* proposed feature for
> addition to C++.  I think, a key issue is whether C++ should just be a
> collection of features.  In other words, does the proposed feature
> usefulness outweights possible downside?

Well, are they that many proposed features that allow detection of
additional errors at compile-time?  I agree with you that we need to
evaluate usefulness vs. drawbacks, but some are arguying that this
feature is not useful at all, which I don't agree with.  I would be
happy if we all could at least agree with the usefulness :)

Regards,

Nicolas

---
[ 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: alain@miniussi.net (Alain Miniussi)
Date: Wed, 11 Dec 2002 19:31:57 +0000 (UTC)
Raw View
Pete Becker wrote:

> Fergus Henderson wrote:
>>
>> Furthermore, no programmer can read documentation that has not yet been
>> written.  But "final" can still be useful in such cases.
>
> I see. This is a replacement for good documentation.

Like private, most const, prototypes and most of the type
systems...

>> For example,
>> suppose your program has an Array class, and you want to add a swap()
>> method to it, which won't work if passed a class derived from Array
>> (as in the example in my earlier post).
>
> I saw where you said that, but saying it doesn't make it true.
>
>> If the Array class is used in
>> a large number of places, it may be difficult to determine whether there
>> is any code which derives from Array.
>
> grep is your friend.

I assume there is an implicit smiley :-)

Alain


---
[ 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: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Wed, 11 Dec 2002 19:42:06 +0000 (UTC)
Raw View
nid_oizo@yahoo.com_removethe_ (Nicolas Fleury) writes:

| Gabriel Dos Reis wrote:
| > nid_oizo@yahoo.com_removethe_ (Nicolas Fleury) writes:
| > [...]
| > | C++ is a language that provides many features to detect errors at
| > | compile-time instead of at run-time.  A final-like feature seems to me
| > | suitable for C++.
| > I think that argument can be made for *any* proposed feature for
| > addition to C++.  I think, a key issue is whether C++ should just be a
| > collection of features.  In other words, does the proposed feature
| > usefulness outweights possible downside?
|
| Well, are they that many proposed features that allow detection of
| additional errors at compile-time?

What the *number* of proposed features that allow detection of
additional errors at compile-time has to do with the above?

My message wasn't intended to be for or against the feature.  Just to
remind a key issue.  Actually, I have no opinion on whether it should
be added or not.  I'm following this discussion in order to make some
opinions.  But, I don't think an answer to your question about
the number would make me vote for or against.

--
Gabriel Dos Reis,       gdr@integrable-solutions.net

---
[ 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: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: Wed, 11 Dec 2002 20:40:53 +0000 (UTC)
Raw View
petebecker@acm.org (Pete Becker) writes:

>Fergus Henderson wrote:
>>
>> petebecker@acm.org (Pete Becker) writes:
>>
>> >Unless you're the user's mother it's not
>> >your responsibility to try to make him into a better programmer.
>>
>> It is every class designer's responsibility to do their best
>> to ensure that the classes that they design are easy to use,
>> and hard to misuse.
>
>That was the goal of Pascal. Look how well it's succeeded.

Pascal failed for other reasons.  Pascal was fundamentally flawed because
it had a strict static type system with no dynamic typing, no polymorphism
and no support for genericity.  Also, it lacked a standard module system.
These factors made code reuse very difficult.

Besides, a million monkeys can choose C and still be wrong.
For example, Pascal had a boolean type, whereas C just had "int".
But the ANSI/ISO C committee eventually realized that this
was a mistake, and added a boolean type.

Anyway, the war ain't over yet ;-)
C syntax is popular, but C# and Java are both closer in semantics to Modula
and Pascal than to C.  The standard libraries of C# and Java are IMHO easier
to use and harder to misuse than those of C or C++, and this is probably a
factor in their popularity.

>> Doing this won't make the users of the class better programmers,
>> but it may well make them produce better programs.
>
>How many program failures do you know of that have resulted from
>inappropriate inheritance and could have been prevented by blocking
>inheritance?

IMHO the main benefit of `final' is not in preventing program failures;
the more important benefits are making programs easier to reason about,
clearer and more concise documentation, and better optimization.

These days I do most of my programming in Mercury, a language in which
these issues don't arise.  But in the past I have seen bugs arise in
C++ code due to deriving from a class without a virtual destructor.

--
Fergus Henderson <fjh@cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.

---
[ 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: pdimov@mmltd.net (Peter Dimov)
Date: Wed, 11 Dec 2002 20:41:02 +0000 (UTC)
Raw View
francis.glassborow@ntlworld.com (Francis Glassborow) wrote in message news:<$pNuc5Bm5199EwR1@robinton.demon.co.uk>...
[...]
> Why is it so hard for programmers to understand that we sometimes need
> ways to disconnect things or be liable for the consequences.

The interesting question is why do you need a new way to disconnect
things when you fail to take advantage of the ways that you currently
have access to. The new way is indeed much easier, but this ease of
use may lead to much more disconnections than necessary.

For the record, some old ways to disconnect are:

- the virtual inheritance lock idiom.

- explicit documentation that "class X shall not be derived from, or
the program is ill-formed, no diagnostic required."

- rewriting functions that expect an operand of type X

void f(X & x);

as

template<class T> void f(T & x)
{
  STATIC_ASSERT(is_same<X, T>::value);
  f_impl(x);
}

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Thu, 12 Dec 2002 01:04:24 +0000 (UTC)
Raw View
Risto Lankinen wrote:
>
> "Pete Becker" <petebecker@acm.org> wrote in message
> news:3DF5382E.3D45AD33@acm.org...
> >
> > There's a great deal of history showing that access protection improves
> > code quality.
>
> Isn't finality a prime example of access protection???
>

No.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: Thu, 12 Dec 2002 01:56:05 +0000 (UTC)
Raw View
petebecker@acm.org (Pete Becker) writes:

>Fergus Henderson wrote:
>>
>> Furthermore, no programmer can read documentation that has not yet been
>> written.  But "final" can still be useful in such cases.
>
>I see. This is a replacement for good documentation.

No matter how disciplined the programmer is about writing good
documentation, sometimes requirements change!

>> If the Array class is used in
>> a large number of places, it may be difficult to determine whether there
>> is any code which derives from Array.
>
>grep is your friend.

`grep Array' gives too many false hits,
and `grep ":.*Array"' gives too many false misses.
I'm sure one could eventually figure out something with sed or perl,
but honestly, programmers have better things to do with their time.

--
Fergus Henderson <fjh@cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.

---
[ 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: alain@miniussi.net (Alain Miniussi)
Date: Thu, 12 Dec 2002 01:56:08 +0000 (UTC)
Raw View
Peter Dimov wrote:

> fjh@cs.mu.OZ.AU (Fergus Henderson) wrote in message
> news:<at1pkf$pd4$1@mulga.cs.mu.OZ.AU>...
>>
>> Why should the bar be set higher for this feature than for other C++
>> features?
>
> It is not.
>
> "final" is being marketed to library designers as it supposedly would
> be useful to them. Library designers aren't buying. Sorry. ;-)

For what I know, most of them are not reading, and I know at least
one former who's slightly in favor :-)

Alain

---
[ 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: alain@miniussi.net (Alain Miniussi)
Date: Thu, 12 Dec 2002 01:56:30 +0000 (UTC)
Raw View
Pete Becker wrote:

> Fergus Henderson wrote:
>>
>> petebecker@acm.org (Pete Becker) writes:
>>
>> >What concrete evidence is there that being able to prevent inheritance
>> >improves program quality?

I have seen a few cases in Java where final improved performances
(which can qualify as a kind of quality) and see no reason why
that wouldn't apply to C++ (although this is only relevant if it
cannot be overriden as I think someone suggested).
It could be argued whether Visitor are a good thing or not, but in
some situation, I have seen clases where visited classes had to
be final.

>> What concrete evidence is there that *any* C++ feature improves
>> program quality?
>
> There's a great deal of history showing that access protection improves
> code quality.

I would assume that people look up the documentation
first and know what they are supposed to do with the class and
how to query its state in the first place.
Enforcing access protection shouldn't make a difference unless
programmers fail to do their homework, but then they probably
won't do a good job anyway.

Isn't it strange to use "history" (to justify an existing
feature while asking for concrete evidence for a new one ?

> There's a great deal of history showing that structured
> programming improves code quality.
>
>>
>> Being able to prevent inheritence means that certain kinds of
>> preconditions, whose violation would lead to program bugs, can easily be
>> statically enforced. That's a fact.
>
> Irrelevant, unless you can show that those cases matter in practice.

They seems to matter to him.

Alain

---
[ 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: dave@boost-consulting.com (David Abrahams)
Date: Thu, 12 Dec 2002 01:56:38 +0000 (UTC)
Raw View
francis.glassborow@ntlworld.com (Francis Glassborow) writes:

> In article <7dc3b1ea.0212110636.6cdedf5e@posting.google.com>, Peter
> Dimov <pdimov@mmltd.net> writes

>>In the absence of documentation explicitly saying "though shalt not
>>derive", derivation from a class is perfectly legal, and not a bug.
>>You must not diagnose it. How many of your classes make that claim in
>>their documentation? My guess is that none do, and this is exactly as
>>it should be, since derivation is not a mistake by itself.
>
> And that is exactly what Fergus et al. have been
> challenging. Sometimes derivation can be a mistake by itself because
> the class designer/implementor knows that the class needs to make
> assumptions about pointers and references that would be broken if
> they happened to point/refer to an instance of a derived type.

He didn't show an example of that, though.  At least, not one which
stands up to Peter's question about operator=().

--
                       David Abrahams
   dave@boost-consulting.com * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution

---
[ 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: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Thu, 12 Dec 2002 01:57:36 +0000 (UTC)
Raw View
In article <7dc3b1ea.0212110616.1ee1ce7b@posting.google.com>, Peter
Dimov <pdimov@mmltd.net> writes
>It's pretty simple, really.
>
>The pro-final argument is that a good designer should utilize final in
>order to produce better designs.

I do not think that represents the general view of the pro group. The
hypothesis is that using final would protect good code from unintended
abuse by less than expert derivation.
>Some of us believe that this is not
>so.
>
>- As a class designer, I don't think that final would enable me to
>produce better designs. (It will not make my job easier.)

But it certainly will not make it harder, and might just possibly
prevent you from wasting large amounts of time explaining to a customer
why (ab)using your library did so much damage.

>
>- As a library designer, I value the ability to use inheritance as an
>implementation detail. Some libraries that currently work perfectly
>well will break when fed final classes. (It will make my job harder.)

Examples. No one is saying that you MUST declare your classes final,
just that owners of classes should be able to do so. If you do not like
that, do not buy their work.

>
>- As an user, I see little use of final. (It will not make my job
>easier.)
>
>- As an user of final classes, I don't expect to be "saved" from any
>mistakes. (It will not make my job easier.)
>
>- As an user, I think that final will be overutilized, as this thread
>has demonstrated. (It will make my job harder.)
>
>Net impact: negative. It will make my job harder.

That is opinion. If it really makes do difference and you really want to
use third party classes that have been marked as final just:

#define final

Of course when something then fails to work it will be abundantly clear
that you knew that you were removing the protection provided by the
owner.

Why are so many people arguing that class designers should be required
to make there classes usable as bases (which they are not because there
is already a mechanism for stopping a class from being derived from, it
is just tortuous).


--
Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ 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: allan_w@my-dejanews.com (Allan W)
Date: Thu, 12 Dec 2002 01:58:31 +0000 (UTC)
Raw View
> Francis Glassborow wrote:
> [...]
> > What I am in favour of (and I think quite a few others are) is the
> > ability to declare that a class is a 'leaf class', i.e. cannot be
> > used as a base class.

terekhov@web.de (Alexander Terekhov) wrote
> Do you have an example of such ``'leaf class', i.e. CANNOT be used as
> a base class.'' [emphases added]. TIA.

Not speaking for Francis, but... How about any class that implements
operator=() this way:

    const Foo &operator=(const Foo&f) {
       if (this != &f) {
          Foo::~Foo();
          new(this) Foo(f);
       }
       return *this;
    }

NOTE -- I'm not advocating this technique, so please don't tell me how
terrible this code is when Foo's constructor can throw, or how it just
isn't smart. The point is, this is the only legal way to implement a
complete operator= when the class contains a reference or a const member.
Furthermore, the C++ standard guarantees that this works, but not if it's
a base class -- which means it ought to be marked Final.

---
[ 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: nid_oizo@yahoo.com_removethe_ (Nicolas Fleury)
Date: Thu, 12 Dec 2002 01:59:06 +0000 (UTC)
Raw View
Gabriel Dos Reis wrote:
> nid_oizo@yahoo.com_removethe_ (Nicolas Fleury) writes:
>
> | Gabriel Dos Reis wrote:
> | > nid_oizo@yahoo.com_removethe_ (Nicolas Fleury) writes:
> | > [...]
> | > | C++ is a language that provides many features to detect errors at
> | > | compile-time instead of at run-time.  A final-like feature seems to me
> | > | suitable for C++.
> | > I think that argument can be made for *any* proposed feature for
> | > addition to C++.  I think, a key issue is whether C++ should just be a
> | > collection of features.  In other words, does the proposed feature
> | > usefulness outweights possible downside?
> |
> | Well, are they that many proposed features that allow detection of
> | additional errors at compile-time?
>
> What the *number* of proposed features that allow detection of
> additional errors at compile-time has to do with the above?

I'm sorry, I guess you were commenting the second sentence when I though
you were commenting the two sentences.  I though you were saying that
detecting errors at compile-time was a an argument for *any* proposed
feature...

Nicolas

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Thu, 12 Dec 2002 01:59:23 +0000 (UTC)
Raw View
"James Kuyper Jr." wrote:
>
> Pete Becker wrote:
> > Fergus Henderson wrote:
> >
> >>petebecker@acm.org (Pete Becker) writes:
> ....
> > create good designs; good designers do. If Joe Programmer in East
> > Oshkosk wants to use your class but can't because you've blocked
> > inheritance then your class isn't easy to use.
>
> That's the purpose of this feature, to make it hard for Joe Programmer
> to use the class this way. That's because such use would constitute
> mis-use of the class. If that's not the case, then the class shouldn't
> be marked 'final'.

Mark Twain had similar advice for making money in the stock market: buy
a stock, and when its price goes up, sell it; if it don't go up, don't
buy it.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Thu, 12 Dec 2002 01:59:29 +0000 (UTC)
Raw View
Nicolas Fleury wrote:
>
> Well, this is not hypothetical, a similar example has happened to me...
>   But what do you mean exactly by concrete evidence then?  Could you
> give an example of a concrete evidence for another C++ feature?  Thx.
>

There's a long history behind information hiding, and that's the basis
for access controls. There's a long history of abuse of goto, and that's
the basis for structured programming. There's a long history of code
complexity and consequent errors in the absence of structured types, and
that's the basis for structs and classes.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Thu, 12 Dec 2002 02:26:12 +0000 (UTC)
Raw View
Allan W wrote:
>
> > Francis Glassborow wrote:
> > [...]
> > > What I am in favour of (and I think quite a few others are) is the
> > > ability to declare that a class is a 'leaf class', i.e. cannot be
> > > used as a base class.
>
> terekhov@web.de (Alexander Terekhov) wrote
> > Do you have an example of such ``'leaf class', i.e. CANNOT be used as
> > a base class.'' [emphases added]. TIA.
>
> Not speaking for Francis, but... How about any class that implements
> operator=() this way:
>
>     const Foo &operator=(const Foo&f) {
>        if (this != &f) {
>           Foo::~Foo();
>           new(this) Foo(f);
>        }
>        return *this;
>     }
>
> NOTE -- I'm not advocating this technique, so please don't tell me how
> terrible this code is when Foo's constructor can throw, or how it just
> isn't smart. The point is, this is the only legal way to implement a
> complete operator= when the class contains a reference or a const member.
> Furthermore, the C++ standard guarantees that this works, but not if it's
> a base class -- which means it ought to be marked Final.
>

Are you giving this example in order to show how to use final, or to
show how to abuse it? If final makes this easier to use that's a pretty
strong argument against final.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Thu, 12 Dec 2002 04:35:31 +0000 (UTC)
Raw View
Francis Glassborow wrote:
>
> Why are so many people arguing that class designers should be required
> to make there classes usable as bases (which they are not because there
> is already a mechanism for stopping a class from being derived from, it
> is just tortuous).
>

I haven't seen anyone say this. Do you have a citation?

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Thu, 12 Dec 2002 06:02:41 +0000 (UTC)
Raw View
Alain Miniussi wrote:
>
> Isn't it strange to use "history" (to justify an existing
> feature while asking for concrete evidence for a new one ?

No, not at all. Concrete evidence is always "history" in one way or
another. Call it prior art if you like, or implementation experience.
Programming techniques didn't just spring, fully formed, out of a
seashell. Most of what beginners today learn to take for granted is
based on years of experience.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Thu, 12 Dec 2002 16:46:46 +0000 (UTC)
Raw View
Fergus Henderson wrote:
>
> `grep Array' gives too many false hits,
> and `grep ":.*Array"' gives too many false misses.

This sounds just like one of those late night TV commercials that try to
convince you to spend far too much money on a new knife by demonstrating
that deliberately clumsy people can make a mess trying to slice a
tomato. But if you really don't know how to use grep then use a browser.
There are lots of ways of finding inheritance paths.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Thu, 12 Dec 2002 16:46:53 +0000 (UTC)
Raw View
Fergus Henderson wrote:
>
> petebecker@acm.org (Pete Becker) writes:
>
> >Fergus Henderson wrote:
> >>
> >> petebecker@acm.org (Pete Becker) writes:
> >>
> >> >Unless you're the user's mother it's not
> >> >your responsibility to try to make him into a better programmer.
> >>
> >> It is every class designer's responsibility to do their best
> >> to ensure that the classes that they design are easy to use,
> >> and hard to misuse.
> >
> >That was the goal of Pascal. Look how well it's succeeded.
>
> Pascal failed for other reasons.  Pascal was fundamentally flawed because
> it had a strict static type system with no dynamic typing, no polymorphism
> and no support for genericity.  Also, it lacked a standard module system.
> These factors made code reuse very difficult.
>

Despite all the same things C has been quite successful. The difference,
of course, is not in the factors you cite but in C's recognition of the
need for flexibility. Most programmers outgrew "Mother, may I" many
years ago.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: pdimov@mmltd.net (Peter Dimov)
Date: Thu, 12 Dec 2002 16:47:16 +0000 (UTC)
Raw View
francis.glassborow@ntlworld.com (Francis Glassborow) wrote in message news:<4M2$lbBI2w99Ewit@robinton.demon.co.uk>...
> In article <7dc3b1ea.0212100455.78c14150@posting.google.com>, Peter
> Dimov <pdimov@mmltd.net> writes
> >"final" is being marketed to library designers as it supposedly would
> >be useful to them. Library designers aren't buying. Sorry. ;-)
>
> You speak for all library designers? If the proponents of final are not
> library designers what are they?

Fair enough.

> No library designer would be compelled to use final were it available.

Some of us are afraid that this would not be the case. You have
already positioned "final" as an "available way to prevent misuse"
that when avoided leads to certain implications. It is likely that
"final" would be described in a similar way in influential C++
publications. Designers would be encouraged to use it.

Furthermore, omission of "final" would be interpreted as an
encouragement to use inheritance by the average C++ programmer. This
thread has clearly demonstrated that many do not understand the
difference between "not explicitly designed for inheritance" and
"explicitly not designed for inheritance".

It is quite likely that "final" will not lead to programmers growing
more familiar with the double-edged sword that is public inheritance.
It might even have the opposite effect.

> Instead of  a resolute no to consideration of final why not get a couple
> of compilers to implement it and gain some experience? Unlike most
> extensions this is one that we would not have a problem with removing
> from code that made use of it because it would just revert to the
> current position.

I don't think that anybody can oppose that, as long as it is someone
else that is funding the effort. Experience, data, facts are always
welcome. In their absence we resort to predictions, as I have done
above.

---
[ 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: pdimov@mmltd.net (Peter Dimov)
Date: Thu, 12 Dec 2002 16:47:31 +0000 (UTC)
Raw View
francis.glassborow@ntlworld.com (Francis Glassborow) wrote in message news:<7JPv0RAsn199EwTC@robinton.demon.co.uk>...
> In article <7dc3b1ea.0212110636.6cdedf5e@posting.google.com>, Peter
> Dimov <pdimov@mmltd.net> writes
> >In the absence of documentation explicitly saying "though shalt not
> >derive", derivation from a class is perfectly legal, and not a bug.
> >You must not diagnose it. How many of your classes make that claim in
> >their documentation? My guess is that none do, and this is exactly as
> >it should be, since derivation is not a mistake by itself.
>
> And that is exactly what Fergus et al. have been challenging. Sometimes
> derivation can be a mistake by itself because the class
> designer/implementor knows that the class needs to make assumptions
> about pointers and references that would be broken if they happened to
> point/refer to an instance of a derived type.

Not correct. Derivation is almost never a mistake in itself, and the
posted example did not demonstrate a case where it is a mistake. The
swap member function would always work as intended. In some cases it
would leave a derived class in an inconsistent state, but the meaning
of "inconsistent" is defined by the design of the derived class and
not by the fact that it has been derived.

There do exist examples where derivation of any kind, even private
inheritance, is a mistake. I will leave the task of coming up with
such an example to the diligent pro-final reader. :-)

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Thu, 12 Dec 2002 18:23:56 +0000 (UTC)
Raw View
Peter Dimov wrote:
>
> francis.glassborow@ntlworld.com (Francis Glassborow) wrote in message news:<4M2$lbBI2w99Ewit@robinton.demon.co.uk>...
> > No library designer would be compelled to use final were it available.
>
> Some of us are afraid that this would not be the case.

Indeed. If it goes into the language, someone's going to stand up at a
standards meeting and propose that we go through the standard library
and mark all the classes that "should" be final.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: terekhov@web.de (Alexander Terekhov)
Date: Thu, 12 Dec 2002 19:50:29 +0000 (UTC)
Raw View
Allan W wrote:
>
> > Francis Glassborow wrote:
> > [...]
> > > What I am in favour of (and I think quite a few others are) is the
> > > ability to declare that a class is a 'leaf class', i.e. cannot be
> > > used as a base class.
>
> terekhov@web.de (Alexander Terekhov) wrote
> > Do you have an example of such ``'leaf class', i.e. CANNOT be used as
> > a base class.'' [emphases added]. TIA.
>
> Not speaking for Francis, but... How about any class that implements
> operator=() this way:
>
>     const Foo &operator=(const Foo&f) {
>        if (this != &f) {
>           Foo::~Foo();
>           new(this) Foo(f);
>        }
>        return *this;
>     }
>
> NOTE -- I'm not advocating this technique, so please don't tell me how
> terrible this code is when Foo's constructor can throw, or how it just
> isn't smart. The point is, this is the only legal way to implement a
> complete operator= when the class contains a reference or a const member.
> Furthermore, the C++ standard guarantees that this works, but not if it's
> a base class -- which means it ought to be marked Final.

Well, < for example >

class Bar : Foo /* ... */ {
  Bar& operator=(const Bar&); // unimplemented
  /* ... */
public:
  /* ... */
};

regards,
alexander.

---
[ 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: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Thu, 12 Dec 2002 19:50:46 +0000 (UTC)
Raw View
In article <3DF7EF39.2FB45485@acm.org>, Pete Becker <petebecker@acm.org>
writes
>Francis Glassborow wrote:
>>
>> Why are so many people arguing that class designers should be required
>> to make there classes usable as bases (which they are not because there
>> is already a mechanism for stopping a class from being derived from, it
>> is just tortuous).
>>
>
>I haven't seen anyone say this. Do you have a citation?

A major argument against 'final' is that it is not up to the class
designer to forbid the use of a class as a base. That argument can be
rephrased to say that class designers should make their classes
available as bases even if doing so would be an abuse.

In fact we already have ways of preventing inheritance but at the cost
of added complexity and fragility. Currently it is mainly expert C++
programmers who know how to do it and so those methods are in relatively
safe hands. I think that those mechanisms will become increasingly
widely known but the understanding of them will not spread as well.

I have no doubt that if final became available, it would be widely used
in an initial flush of enthusiasm, but writers like Herb Sutter and
Scott Meyers could turn their attention to making more better informed.

However those who might abuse final are hardly likely to be the kind of
competent library designer whose products become widely available.

It seems to me that final might allow experts who wish to do so (because
their designs rely on invariants that are likely to be violated by
inheritance) to use it to protect lesser programmers from 'error' while
at the same time allowing those lesser programmers to abuse final. How
is that new? No doubt as mutable becomes better known by programmers who
lack competence, that will be abused as a way of fixing const member
functions that will not compile.

Hey, that gives me an idea, lets have a new guideline propagated in the
week before the next WG21 meeting:

Declare all member functions as const, and all member data as mutable.


--
Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Thu, 12 Dec 2002 19:51:18 +0000 (UTC)
Raw View
Francis Glassborow wrote:
>
> In article <7dc3b1ea.0212110616.1ee1ce7b@posting.google.com>, Peter
> Dimov <pdimov@mmltd.net> writes
> >It's pretty simple, really.
> >
> >The pro-final argument is that a good designer should utilize final in
> >order to produce better designs.
>
> I do not think that represents the general view of the pro group. The
> hypothesis is that using final would protect good code from unintended
> abuse by less than expert derivation.

Then the hypothesis is wrong. There is nothing about final that
guaruantees that it will only be used in this way. Indeed, the naive
claims made about it in this thread indicate that it will be widely
abused. Of course, if it's overridable then overriding it will become
automatic, and it will go the way of 'auto'.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: rmaddox@isicns.com (Randy Maddox)
Date: Thu, 12 Dec 2002 19:51:25 +0000 (UTC)
Raw View
petebecker@acm.org (Pete Becker) wrote in message news:<3DF7EF39.2FB45485@acm.org>...
> Francis Glassborow wrote:
> >
> > Why are so many people arguing that class designers should be required
> > to make there classes usable as bases (which they are not because there
> > is already a mechanism for stopping a class from being derived from, it
> > is just tortuous).
> >
>
> I haven't seen anyone say this. Do you have a citation?
>
> --
> Pete Becker
> Dinkumware, Ltd. (http://www.dinkumware.com)
>

I concur that no one in this thread has actually said exactly what
Francis Glassborow indicates above, but several people have definitely
stated that argued that there is no need for support to prevent
derivation.  The proposal for final to allow a class designer to
explicitly state in a concise way that can be understood by both
developers and the compiler has been categorized in this thread as:
"arrogant", "if your class cannot be derived from then it is not easy
to use", "the user of a class knows best", etc.  IMHO, this is
essentially equivalent to insisting that all classes support
derivation.  If no class is allowed to prevent derivation is this not
the same as saying that all classes must allow derivation?

The arguments that I have not seen made are the counters to the
following:

1) There are indeed some classes which are best treated as leaf
classes, i.e., not suitable for use as a base class.

2) The designer of a class is in the best position to know whether or
not they have made assumptions in the implementation of a class that
would cause that class to fall into the category of best used as a
leaf class.

3) There are already tortuous techniques that can be applied to
support the idiom of a leaf class, which would seem to indicate that
there is indeed a real-world need for this idiom.

4) Comments, documentation, convention, etc. are a very weak reed
compared to explicit compiler support.

Unless someone can make an overpowering argument that there is never
any good reason to deliberately design a class as a leaf class, or
that the user of a class always knows better than the designer of a
class, or that there are some as yet not pointed out overwhelming
costs to this proposal, then IMHO the counter arguments are much
weaker than the arguments in favor of final.

Randy.

---
[ 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: dave@boost-consulting.com (David Abrahams)
Date: Thu, 12 Dec 2002 19:51:42 +0000 (UTC)
Raw View
francis.glassborow@ntlworld.com (Francis Glassborow) writes:

> In article <7dc3b1ea.0212110616.1ee1ce7b@posting.google.com>, Peter
> Dimov <pdimov@mmltd.net> writes
>>It's pretty simple, really.
>>
>>The pro-final argument is that a good designer should utilize final in
>>order to produce better designs.
>
> I do not think that represents the general view of the pro group. The
> hypothesis is that using final would protect good code from unintended
> abuse by less than expert derivation.

That part is probably true, if you rephrase it: "it would prevent some
illegitimate uses of derivation, and some legitimate ones".

>>- As a library designer, I value the ability to use inheritance as an
>>implementation detail. Some libraries that currently work perfectly
>>well will break when fed final classes. (It will make my job harder.)
>
> Examples.

See:

   http://www.boost.org/libs/utility/compressed_pair.htm

and the is_polymorphic trait at:

   http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/*checkout*/boost/boost/libs/type_traits/index.htm#properties

Both of which depend on the ability to derive from a template
parameter.  These are just two off the top of my head.

> No one is saying that you MUST declare your classes final,
> just that owners of classes should be able to do so. If you do not
> like that, do not buy their work.

When you're a template designer, you have to "buy" the work of anybody
whose class is used as a template parameter.  If my users "buy" a
final class and pass it to my template which eventually tries to use
it as a base, I'm stuck explaining why.

> That is opinion. If it really makes do difference and you really
> want to use third party classes that have been marked as final just:
>
> #define final

That's not really an option for the class template designer.

> Of course when something then fails to work it will be abundantly
> clear that you knew that you were removing the protection provided by
> the owner.
>
> Why are so many people arguing that class designers should be required
> to make there classes usable as bases (which they are not because
> there is already a mechanism for stopping a class from being derived
> from, it is just tortuous).

Francis, I think you're missing the point.  There is absolutely
nothing a class designer can do /semantically/ to make a class utterly
unsuitable as a base in the current language (the tortuous virtual
base trick you're describing just does it syntactically).  Nobody's
arguing that class designers should be required to do anything they're
not already doing.  A class that doesn't use the tortuous trick
already is usable as a base.

--
                       David Abrahams
   dave@boost-consulting.com * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution

---
[ 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: pdimov@mmltd.net (Peter Dimov)
Date: Thu, 12 Dec 2002 19:51:56 +0000 (UTC)
Raw View
francis.glassborow@ntlworld.com (Francis Glassborow) wrote in message news:<ZFmnnnIII799EwWC@robinton.demon.co.uk>...
> In article <7dc3b1ea.0212110616.1ee1ce7b@posting.google.com>, Peter
> Dimov <pdimov@mmltd.net> writes
> >It's pretty simple, really.
> >
> >The pro-final argument is that a good designer should utilize final in
> >order to produce better designs.
>
> I do not think that represents the general view of the pro group. The
> hypothesis is that using final would protect good code from unintended
> abuse by less than expert derivation.

Could someone please provide a summary of the general view of the pro
group. What is "final"? What kinds of inheritance does it block? Which
standard library classes should be marked "final"? When should "final"
be used?

> >Some of us believe that this is not
> >so.
> >
> >- As a class designer, I don't think that final would enable me to
> >produce better designs. (It will not make my job easier.)
>
> But it certainly will not make it harder, and might just possibly
> prevent you from wasting large amounts of time explaining to a customer
> why (ab)using your library did so much damage.

My prediction is that it will not.

> >- As a library designer, I value the ability to use inheritance as an
> >implementation detail. Some libraries that currently work perfectly
> >well will break when fed final classes. (It will make my job harder.)
>
> Examples.

The burden of proof is typically on the other side. ;-)

Inheritance is sometimes used instead of containment as an
implementation detail for the following reasons:

- Empty base optimization.
- You need this subobject initialized before another base class.
- It is difficult to replicate the interface of the subobject using
forwarding as the interface might be unknown.

Boost has a number of such examples, if you know where to look. (The
type traits even do Evil Things(tm) with inheritance.) It's not
necessary to hunt them down, of course. Simply mark your class as
__final using your favorite compiler that provides this extension and
see what works and what doesn't.

> No one is saying that you MUST declare your classes final,
> just that owners of classes should be able to do so. If you do not like
> that, do not buy their work.

The point of the above is that I'll have to worry about final classes
breaking my libraries, regardless of whether I buy something or not.

> >Net impact: negative. It will make my job harder.
>
> That is opinion.

Everything in this thread is an opinion. If you think that my opinion
is worthless, so be it.

> If it really makes do difference and you really want to
> use third party classes that have been marked as final just:
>
> #define final

This is an ODR violation.

[...]

> Why are so many people arguing that class designers should be required
> to make there classes usable as bases (which they are not because there
> is already a mechanism for stopping a class from being derived from, it
> is just tortuous).

You must have been reading some other thread. ;-)

---
[ 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: alain@miniussi.net (Alain Miniussi)
Date: Thu, 12 Dec 2002 19:52:10 +0000 (UTC)
Raw View
Fergus Henderson wrote:

> petebecker@acm.org (Pete Becker) writes:
>
>>Fergus Henderson wrote:
>>>
>>> Furthermore, no programmer can read documentation that has not yet been
>>> written.  But "final" can still be useful in such cases.
>>
>>I see. This is a replacement for good documentation.
>
> No matter how disciplined the programmer is about writing good
> documentation, sometimes requirements change!
>
>>> If the Array class is used in
>>> a large number of places, it may be difficult to determine whether there
>>> is any code which derives from Array.
>>
>>grep is your friend.
>
> `grep Array' gives too many false hits,
> and `grep ":.*Array"' gives too many false misses.
> I'm sure one could eventually figure out something with sed or perl,

Not so sure, for one, you need the list of all the file to consider,
even if you assume that you can alway start looking from "/", it
requires the list of all the disks to look on, and an
autorisation to look into those disks (justifying running that
script in the background at customers site might be an
interesting exercise).

Now, assuming that, somehow, you find a way to get all those
information, and assuming that time is not an issue, the nice thing
is that you can probably modify your technologie to detect access
violation, so we don't really need access specifiers anymore.

> but honestly, programmers have better things to do with their time.

The lucky ones.

Alain


---
[ 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: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Thu, 12 Dec 2002 19:52:20 +0000 (UTC)
Raw View
In article <3DF8C945.7E447987@acm.org>, Pete Becker <petebecker@acm.org>
writes
>Peter Dimov wrote:
>>
>> francis.glassborow@ntlworld.com (Francis Glassborow) wrote in message news:<4M2$lbBI2w99Ewit@robinton.demon.co.uk>...
>> > No library designer would be compelled to use final were it available.
>>
>> Some of us are afraid that this would not be the case.
>
>Indeed. If it goes into the language, someone's going to stand up at a
>standards meeting and propose that we go through the standard library
>and mark all the classes that "should" be final.

I see, even those designing the language cannot be trusted. I think that
the overwhelming majority of our colleagues are better than that.

Actually, one feature is that no published class can be declared final
as that would potentially break existing code and therefore, whilst
favouring at least experiments with final I would also oppose applying
it to any element of the existing Standard C++ Library. And I am certain
that that would be the general consensus.



--
Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Thu, 12 Dec 2002 19:57:20 +0000 (UTC)
Raw View
Francis Glassborow wrote:
>
> In article <3DF7EF39.2FB45485@acm.org>, Pete Becker <petebecker@acm.org>
> writes
> >Francis Glassborow wrote:
> >>
> >> Why are so many people arguing that class designers should be required
> >> to make there classes usable as bases (which they are not because there
> >> is already a mechanism for stopping a class from being derived from, it
> >> is just tortuous).
> >>
> >
> >I haven't seen anyone say this. Do you have a citation?
>
> A major argument against 'final' is that it is not up to the class
> designer to forbid the use of a class as a base. That argument can be
> rephrased to say that class designers should make their classes
> available as bases even if doing so would be an abuse.

"Available as bases" means something rather different from "usable as
bases." And, of course, whether it's an abuse is in the eye of the user.

> It seems to me that final might allow experts who wish to do so (because
> their designs rely on invariants that are likely to be violated by
> inheritance) to use it to protect lesser programmers from 'error' while
> at the same time allowing those lesser programmers to abuse final.

That might be so, if it was library experts who were asking for this.
That doesn't appear to be the case, though.

> Hey, that gives me an idea, lets have a new guideline propagated in the
> week before the next WG21 meeting:
>
> Declare all member functions as const, and all member data as mutable.
>

Propose whatever you like.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Thu, 12 Dec 2002 20:12:34 +0000 (UTC)
Raw View
Randy Maddox wrote:
>
> petebecker@acm.org (Pete Becker) wrote in message news:<3DF7EF39.2FB45485@acm.org>...
> > Francis Glassborow wrote:
> > >
> > > Why are so many people arguing that class designers should be required
> > > to make there classes usable as bases (which they are not because there
> > > is already a mechanism for stopping a class from being derived from, it
> > > is just tortuous).
> > >
> >
> > I haven't seen anyone say this. Do you have a citation?
> >
> > --
> > Pete Becker
> > Dinkumware, Ltd. (http://www.dinkumware.com)
> >
>
> I concur that no one in this thread has actually said exactly what
> Francis Glassborow indicates above,

In fact, Francis Glassborow no longer says it.

> but several people have definitely
> stated that argued that there is no need for support to prevent
> derivation.  The proposal for final to allow a class designer to
> explicitly state in a concise way that can be understood by both
> developers and the compiler has been categorized in this thread as:
> "arrogant", "if your class cannot be derived from then it is not easy
> to use", "the user of a class knows best", etc.  IMHO, this is
> essentially equivalent to insisting that all classes support
> derivation.  If no class is allowed to prevent derivation is this not
> the same as saying that all classes must allow derivation?

Yes. But "allow" is different from "make usable."

>
> The arguments that I have not seen made are the counters to the
> following:
>
> 1) There are indeed some classes which are best treated as leaf
> classes, i.e., not suitable for use as a base class.

Yup. That doesn't mean that a class designer must actively prevent
inheriting from them.

>
> 2) The designer of a class is in the best position to know whether or
> not they have made assumptions in the implementation of a class that
> would cause that class to fall into the category of best used as a
> leaf class.

Nope. The designer of a base class doesn't know anything about the
user's problem domain.

>
> 3) There are already tortuous techniques that can be applied to
> support the idiom of a leaf class, which would seem to indicate that
> there is indeed a real-world need for this idiom.

Nope. They indicate that some people want to do it. That's different
from indicating a need. Not everything that someone wants to do should
be standardized.

>
> 4) Comments, documentation, convention, etc. are a very weak reed
> compared to explicit compiler support.

Yup. Save the big guns for the big problems.

>
> Unless someone can make an overpowering argument that there is never
> any good reason to deliberately design a class as a leaf class, or
> that the user of a class always knows better than the designer of a
> class, or that there are some as yet not pointed out overwhelming
> costs to this proposal, then IMHO the counter arguments are much
> weaker than the arguments in favor of final.
>

Unless someone can make an overpowering argument that inappropriate
inheritance is a significant problem for class writers today there is no
need for a language change. So far noboby has mentioned a single case
where inheritance caused problems that could have been prevented with
something like final. Current techniques for preventing inheritance are
more than adequate for dealing with hypothetical problems.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: alain@miniussi.net (Alain Miniussi)
Date: Tue, 17 Dec 2002 18:13:07 +0000 (UTC)
Raw View
Hyman Rosen wrote:

> Alain Miniussi wrote:
>  > Doing such optimization by hand,
>> and I have seen such evil, is likely to fail at
>> some point.
>
> You mean this: p->Derived::f() ?

It was worse actually, but it could have been this.

Alain

---
[ 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: pdimov@mmltd.net (Peter Dimov)
Date: Tue, 17 Dec 2002 18:13:12 +0000 (UTC)
Raw View
allan_w@my-dejanews.com (Allan W) wrote in message news:<7f2735a5.0212161806.1e64e9de@posting.google.com>...
> pdimov@mmltd.net (Peter Dimov) wrote
> > francis.glassborow@ntlworld.com (Francis Glassborow) wrote
> > > Final would at least allow you to document that your classes and
> > > templates will not work with final classes.
> >
> > I don't see how "final" would help me to write documentation.
>
> Please allow me to demonstrate. Here's the version without final:
>
>     struct shape {
>         ~shape()=0;
>         void draw() = 0;
>         // ... etc ...
>     };
>     shape::~shape() {};
>
>     struct circle : public shape { // Do not derive from this class!
>         circle(double center_x, center_y, radius);
>         ~circle() {}
>         void draw(); // Defined elsewhere
>     };

[...]

Thank you for the example. Here's how I would have written it:

class shape
{
protected:

   ~shape() {}

public:

   virtual void draw() = 0;
};

shared_ptr<shape> create_circle();
shared_ptr<shape> create_rectangle();
shared_ptr<shape> create_other();

---
[ 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: pdimov@mmltd.net (Peter Dimov)
Date: Tue, 17 Dec 2002 18:13:18 +0000 (UTC)
Raw View
rmaddox@isicns.com (Randy Maddox) wrote in message news:<8c8b368d.0212161107.41f20941@posting.google.com>...
>
> If you had not clipped so much of the context it would have been clear
> that Scott Mayo was not suggesting that C++ emulate Java, but rather
> citing Java as an example of prior art in the use of the 'final'
> concept.  In particular note the restored context here:
>
> "In summary, 'final' is cheap to implement, has prior art in Java, and
> represents a clear way to specify something that can be specified
> now, but using idioms which are obscure (maybe not to people
> here, but to many C++ programmers who are not language wonks.)"

All of the above is true, but the discussion is about whether the
benefits of final in C++ outweigh its disadvantages. Experience with
the Java "final" can potentially be used to demonstrate the benefits,
but we haven't seen any real data so far. The only firm data point is
that there are no objections to final in Java.

---
[ 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: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: Tue, 17 Dec 2002 19:02:47 +0000 (UTC)
Raw View
petebecker@acm.org (Pete Becker) writes:

 >Fergus Henderson wrote:
 >>
 >> petebecker@acm.org (Pete Becker) writes:
 >>
 >> >Fergus Henderson wrote:
 >> >>
 >> >> petebecker@acm.org (Pete Becker) writes:
 >> >>
 >> >> >Unless you're the user's mother it's not
 >> >> >your responsibility to try to make him into a better programmer.
 >> >>
 >> >> It is every class designer's responsibility to do their best
 >> >> to ensure that the classes that they design are easy to use,
 >> >> and hard to misuse.
 >> >
 >> >That was the goal of Pascal. Look how well it's succeeded.
 >>
 >> Pascal failed for other reasons.  Pascal was fundamentally flawed because
 >> it had a strict static type system with no dynamic typing, no polymorphism
 >> and no support for genericity.  Also, it lacked a standard module system.
 >> These factors made code reuse very difficult.
 >
 >Despite all the same things C has been quite successful.

C didn't have "all the same things".

C didn't have a strict static type system -- it had a quite weak static
type system, which could be easily circumvented with casts, unions,
etc.  Unlike Pascal, C provided support for genericity and polymorphism
using `void *' (or `char *' in pre-ANSI C) and by allowing function
pointers in data structures.  And while neither C nor Pascal had a
standard module system as such, C has a standard substitute for a module
system, whereas Pascal did not.  (C's substitute for a module system is
the C preprocessor's #include feature, combined with the #ifndef header
guard hack to avoid problems with multiple inclusion.)

--
Fergus Henderson <fjh@cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.

---
[ 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: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: Tue, 17 Dec 2002 21:21:18 +0000 (UTC)
Raw View
kanze@gabi-soft.de (James Kanze) writes:

>I think Dave Harris hit the nail on the head when he spoke about
>preventing overriding of functions.  Normally, the only danger to my
>code when you inherit from my class is that you override some of the
>virtual functions, but not all, and that the virtual functions work
>together to ensure class invariants.

It's not just that.  There's also the issue of passing a derived
class where a base class is expected, which can break the preconditions
of functions like swap() which expect that their arguments point
or refer to the class specified, not to a derived class with additional
data members.

--
Fergus Henderson <fjh@cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.

---
[ 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: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: Tue, 17 Dec 2002 21:26:39 +0000 (UTC)
Raw View
petebecker@acm.org (Pete Becker) writes:

>Fergus Henderson wrote:
>>
>> `grep Array' gives too many false hits,
>> and `grep ":.*Array"' gives too many false misses.
>
>This sounds just like one of those late night TV commercials that try to
>convince you to spend far too much money on a new knife by demonstrating
>that deliberately clumsy people can make a mess trying to slice a
>tomato.  But if you really don't know how to use grep...

I know how to use grep.
I am not being deliberately obtuse.

I do not believe that standard grep alone can be easily used to
accurately find inheritence paths.  If there is an easy way to use
grep to solve this problem, then post it.

>But if you really don't know how to use grep then use a browser.

Class hierarchy browsers generally don't catch template classes for which
there are no instantiations.  Also, they require that the program be
in a compilable state, which is often not the case during maintenance.

>There are lots of ways of finding inheritance paths.

That's true.  But as far as I can tell, they all have their disadvantages.
None of them are as sure and as simple as adding "final" would be.

--
Fergus Henderson <fjh@cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Tue, 17 Dec 2002 21:37:20 +0000 (UTC)
Raw View
Fergus Henderson wrote:
>
> Class hierarchy browsers generally don't catch template classes for which
> there are no instantiations.  Also, they require that the program be
> in a compilable state, which is often not the case during maintenance.
>

In which case final won't help you, either.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: scottm@toast.net ("Scott Mayo")
Date: Tue, 17 Dec 2002 22:46:33 +0000 (UTC)
Raw View
"Pete Becker" <petebecker@acm.org> wrote in message
news:3DFE7645.DA05A56E@acm.org...
>Me:

> > "In summary, 'final' is cheap to implement, has prior art in Java, and
> > represents a clear way to specify something that can be specified
> > now, but using idioms which are obscure (maybe not to people
> > here, but to many C++ programmers who are not language wonks.)"

> Java practices are not prior art for C++, although they might be
> considered prior graffiti. Java is a different language with different
> design goals and a different runtime environment. Even if final is good
> in Java that doesn't say anything about its utility in C++.

For pity's sake. I dislike Java too, but I'm not willing to dismiss
an entire language out of hand. It turns out that Java has a structure
roughly similar to C++ in terms of classes, and 'final' has the
same semantics as it would in C++. 'final' solves a problem in
Java (even if you don't agree that there is such a problem), and
Java has demonstrated that the solution in question hasn't caused
the world to end. This is about the clearest demonstration of
prior art that a new idea for C++ can have. To get anything
better, someone would actually have to implement it in a C++
compiler and report back the results.

I don't like post-modern paining very much, but I don't
dismiss it as graffiti (except perhaps when it's done by
elephants).

>Last I looked, people weren't complaining that
>C++ code was just too slow.

For some of us - I do game programming for fun, and real time
systems professionally - C++ is most useful when aggressively
optimized. I *can* point to cases where individual instructions
mattered (as did CPU cache hit activity), and cases where std
functions were out of bounds, because they allocated memory
and the cost of an alloc was simply out of the question. I realize
that in this respect I'm out on the fringe, but maybe not that
far out - C++'s last justification in the business world is simply
this: it's what you use when the Java programmers have already
tried, and couldn't get the necessary performance. (I quietly
believe that if Java had been given faster String behaviour, C++
would already be all but gone from the business world.)

My employers are requiring me to learn Java because they've
essentially decided that C++ is too complex to learn, too
extendable and abusable to maintain, and too prone to
portability problems. The last toehold left is that C++,
carefully hand-coded and optimized, runs rings around
Java in terms of performance. For me, 'final' is another
way to justify C++ in a world which is starting to question
why C++ is needed at all.




---
[ 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: alain@miniussi.net (Alain Miniussi)
Date: Tue, 17 Dec 2002 22:47:15 +0000 (UTC)
Raw View
Pete Becker wrote:

> Alain Miniussi wrote:
>>
>> As an example, consider the Visitor design pattern,
>> In the body of a Visitor function, I have no reason to
>> pay the price of a virtual call when invoquing a method
>> on the visited object.
>
> And how high is the price of a virtual call?

Having "final" allow me to make the choice, since you seems
to be opposed to "final", I suspect you know (somehow) that
that price is never high enough.
So, you tell me, how high is the price of a virtual call ? :-)
Compared to say, an inlined function ? (if it's final it can
be inlined).
And compared to a plain local function ? is it the same on
all architecture ? (on IA64, virtual function are never
considered local, is the difference bug enough ? well, I
do not have any numbers, but somehow, someone decided it
was worth introducing the notion of local functions on
that architecture).

With "final", I can adapt.

> Have you
> determined that virtual calls are a bottleneck in your
> program?

Well, what if I did ? :-)
If "inline" is justified, we accept the fact that function
call can be too expensive, and virtual call are more expensive
than plain calls.

But to answer your question, I have seen differences that were
considered important enough to address the issue. I haven't seen
a program spending 80% of its time loading a fct pointer through
a vtable, if that's what you're asking (actually, I did, but it
was made on purpose)).
I have also seens cases where, correctly or not, it was
believed to be important enough to screw the code.

I think the example of Java has already be pointed as
existing pratice, and I do not remember seing any valid
argument opposed (a valid argument would be an explanation
of why the reasons that makes it sensible in Java do not
apply to C++, or an argument showing it is not sensible
in Java to start with). I'll admit I haven't looked closely
to the whole thread so I could have missed it.

Please note that the fact I am only addressing efficiency
issue, that doesn't mean it is the only reason to have final
(as a matter of fact, it seems to me that if we accept the
fact that someone need a reason to allow a sub-class
to override a method, it is consistent to allow to prohibit
such overriding, should that reason be absent. Also, if I can
decide that a method should not be overriden, why
should that decision be systematicaly invalidated by the fact
it was virtual in a parent class?). But I supect it's already
been addressed, based on the size of the thread, plus I don't
expect a huge improvment in current C++ coding practice
because of it, so I don't think it will address an important
practical problem in that area, it's just that I don't think
it will hurt either.

Also note that I can live a perfectly happy life whithout
"final", but the only cost I see associated with it is that
"final" is not a reserved word. So the benefit does not have
to be that big for it to be considered.

Regards,


Alain

---
[ 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: alain@miniussi.net (Alain Miniussi)
Date: Tue, 17 Dec 2002 22:47:36 +0000 (UTC)
Raw View
Bob Bell wrote:

> alain@miniussi.net (Alain Miniussi) wrote in message
> news:<uvsp6c6n5p6n46@corp.supernews.com>...
>> Hyman Rosen wrote:
>>
>> > Alain Miniussi wrote:
>> >> How do you fix the perf issue in C++ ?
>> >
>> > By not making the methods virtual in the first place.
>>
>> That's not the case I'm talking about.
>>
>> My method *is* virtual in some base class, in some
>> derived, probably leaf, class, I want to stop that.
>> I can do that in Java, how do I do that in C++ ?
>
> Do you know that this is really a problem? How important are the
> optimizations that final makes possible?

>From a virtual call to an inlined function. I am not
saying it is the only solution, just that it makes
things more simple.

>> As an example, consider the Visitor design pattern,
>> In the body of a Visitor function, I have no reason to
>> pay the price of a virtual call when invoquing a method
>> on the visited object.
>
> It seems to me that if you don't need the virtual call, then you
> probably don't need the function to be virtual in the first place.
>
> Perhaps you can describe a little more what kind of scenario you're
> imagining?

You have a hierarchy of classes such that you can apply the visitor
DP on them (eg: the hierarchy is stable enough, won't be extended
outside a given library blablabla..).
You have an action "fct" to perform on instances of those classes,
which involve manipulating those classes throught virtual methods
m1... m42. Without using visitor, an manipulatin the objects through
"Root& obj" you have to pay the price of the virtual call for each
individual call (actually, you could imagine that fct start loading
the obj.vtable once, and then uses the same table for the rest
of the function, but each time I looked, the compiler was too shy
to do that, maybe for good reason, who knows) because the dynamic
binding will recovers the "real" type for each call m1... m42.
With the visitor, things are differents, once I have paid for the
double dispatch, I know what concrete type I am dealing with, and
since it is typicalyy a leaf class, I know which m1...m42 to call.
Of course, I could then decide to do it by hand, using qualified
calls, but it doesn't look like a very nice solution to me.

Of course, you can dismiss that scenario (because I guess I could),
and there are other scenari. But the point is, I guess, that in
some cases, virtual calls could be avoided if you know that you
are dealing with a class for which no derived class override a
given method.

In abscence of dynamic linking, global optimization could deal
with that sort of optimization. I suspect it could be possible
even in presence of dynamic linking, but more difficult.
If it become available at some point, then that usage of
final will become as irrelevant as "register" and "inline"
:-)

Regards,

Alain

---
[ 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: dave@boost-consulting.com (David Abrahams)
Date: Tue, 17 Dec 2002 22:47:47 +0000 (UTC)
Raw View
fjh@cs.mu.OZ.AU (Fergus Henderson) writes:

> pdimov@mmltd.net (Peter Dimov) writes:
>
>  >
>  >class X
>  >{
>  >public:
>  >
>  >  virtual void f() = 0;
>  >
>  >protected:
>  >
>  >  ~X() {}
>  >};
>  >
>  >class impl: public X
>  >{
>  >public:
>  >
>  >  virtual void f() {}
>  >};
>  >
>  >boost::shared_ptr<X> px(new impl);
>
> I don't understand.  Won't that result in undefined behaviour
> when px's destructor is called?

No. This is not your father's shared_ptr<T>.

-Dave
--
                       David Abrahams
   dave@boost-consulting.com * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution

---
[ 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: allan_w@my-dejanews.com (Allan W)
Date: Tue, 17 Dec 2002 22:50:48 +0000 (UTC)
Raw View
Pete Becker <petebecker@acm.org> wrote in message news:<3DFD127A.DAEBC78@acm.org>...
> Scott Mayo wrote:
> >
> > I don't know of a hue and cry against 'final' in Java, though I suppose
> > opponents could claim this is because final is so necessary (Java
> > performs hideously without it) that it has ceased to be seen as evil.
> >
>
> Java isn't C++. There are many things that Java has done that we
> shouldn't emulate in C++.

On the other hand, C++ shouldn't shy away from them just because Java
already did them. This is not a competition.

In Java, you use the "+" operator to add two integers. Should we change
this for C++, just to be different? C++ did it before Java did; should
we demand that the Java language change this, just for the sake of
being different?

It seems to me that Scott wasn't saying, "We should do whatever Java does."
Instead, I think Scott was saying, "Here's a case where the keyword being
debated was useful -- which proves that it CAN be useful. That doesn't mean
that this keyword is the only way to do it -- but it does work, so please
consider that as you deliberate about using it yourselves."

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Tue, 17 Dec 2002 22:50:54 +0000 (UTC)
Raw View
Francis Glassborow wrote:
>
> In article <3DFE7645.DA05A56E@acm.org>, Pete Becker <petebecker@acm.org>
> writes
> >Java practices are not prior art for C++, although they might be
> >considered prior graffiti. Java is a different language with different
> >design goals and a different runtime environment. Even if final is good
> >in Java that doesn't say anything about its utility in C++.
>
> But WG21 frequently considered that what had been done in other
> languages was prior art. You may disagree that that is a correct view of
> prior art,  but it is your opinion rather than fact.
>

It is my opinion that merely pointing out that some other language has
some feature does not justify adding that feature to C++. Is that also
your opinion?

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Tue, 17 Dec 2002 22:51:06 +0000 (UTC)
Raw View
Fergus Henderson wrote:
>
> petebecker@acm.org (Pete Becker) writes:
>
>  >Fergus Henderson wrote:
>  >>
>  >> petebecker@acm.org (Pete Becker) writes:
>  >>
>  >> >Fergus Henderson wrote:
>  >> >>
>  >> >> petebecker@acm.org (Pete Becker) writes:
>  >> >>
>  >> >> >Unless you're the user's mother it's not
>  >> >> >your responsibility to try to make him into a better programmer.
>  >> >>
>  >> >> It is every class designer's responsibility to do their best
>  >> >> to ensure that the classes that they design are easy to use,
>  >> >> and hard to misuse.
>  >> >
>  >> >That was the goal of Pascal. Look how well it's succeeded.
>  >>
>  >> Pascal failed for other reasons.  Pascal was fundamentally flawed because
>  >> it had a strict static type system with no dynamic typing, no polymorphism
>  >> and no support for genericity.  Also, it lacked a standard module system.
>  >> These factors made code reuse very difficult.
>  >
>  >Despite all the same things C has been quite successful.
>
> C didn't have "all the same things".
>
> C didn't have a strict static type system -- it had a quite weak static
> type system, which could be easily circumvented with casts, unions,
> etc.  Unlike Pascal, C provided support for genericity and polymorphism
> using `void *' (or `char *' in pre-ANSI C) and by allowing function
> pointers in data structures. And while neither C nor Pascal had a
> standard module system as such, C has a standard substitute for a module
> system, whereas Pascal did not.  (C's substitute for a module system is
> the C preprocessor's #include feature, combined with the #ifndef header
> guard hack to avoid problems with multiple inclusion.)
>

Oh, I see: you're talking about standard Pascal, not the dialects that
actually had some commercial success. Borland Pascal provides pretty
much the same set of features as you outline above. It's a niche
product.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: allan_w@my-dejanews.com (Allan W)
Date: Tue, 17 Dec 2002 22:51:09 +0000 (UTC)
Raw View
alain@miniussi.net (Alain Miniussi) wrote
> How do you fix the perf issue in C++ ? The only solution
> I can think of (without final) implies global optimization
> and no dynamic linking.

Would you please elaborate on the perf(ormance?) issue?

Are you pointing out that virtual function calls take longer than
standard function calls? If so, please perform some simple statistics
and report back -- while the performance difference does exist, I
think you might be surprised just how minor they are. And remember
that it happens only when you call a function virtually.

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Tue, 17 Dec 2002 23:13:53 +0000 (UTC)
Raw View
Scott Mayo wrote:
>
> "Pete Becker" <petebecker@acm.org> wrote in message
> news:3DFE7645.DA05A56E@acm.org...
> >Me:
>
> > > "In summary, 'final' is cheap to implement, has prior art in Java, and
> > > represents a clear way to specify something that can be specified
> > > now, but using idioms which are obscure (maybe not to people
> > > here, but to many C++ programmers who are not language wonks.)"
>
> > Java practices are not prior art for C++, although they might be
> > considered prior graffiti. Java is a different language with different
> > design goals and a different runtime environment. Even if final is good
> > in Java that doesn't say anything about its utility in C++.
>
> For pity's sake. I dislike Java too, but I'm not willing to dismiss
> an entire language out of hand. It turns out that Java has a structure
> roughly similar to C++ in terms of classes, and 'final' has the
> same semantics as it would in C++.

Really? I've heard several different versions of final mentioned here,
some of which are clearly different from Java. The ones that aren't
clearly different aren't detailed enough to make that determination.

> 'final' solves a problem in
> Java

Which problem do you claim it solves?

> (even if you don't agree that there is such a problem), and
> Java has demonstrated that the solution in question hasn't caused
> the world to end. This is about the clearest demonstration of
> prior art that a new idea for C++ can have. To get anything
> better, someone would actually have to implement it in a C++
> compiler and report back the results.

Good idea.

>
> I don't like post-modern paining very much, but I don't
> dismiss it as graffiti (except perhaps when it's done by
> elephants).
>
> >Last I looked, people weren't complaining that
> >C++ code was just too slow.
>
> For some of us - I do game programming for fun, and real time
> systems professionally - C++ is most useful when aggressively
> optimized. I *can* point to cases where individual instructions
> mattered (as did CPU cache hit activity), and cases where std
> functions were out of bounds, because they allocated memory
> and the cost of an alloc was simply out of the question.

Now all you need to do is demonstrate that final would lead to speed
improvements comparable to those obtained by avoiding allocating from
the free store.

> I realize
> that in this respect I'm out on the fringe, but maybe not that
> far out - C++'s last justification in the business world is simply
> this: it's what you use when the Java programmers have already
> tried, and couldn't get the necessary performance. (I quietly
> believe that if Java had been given faster String behaviour, C++
> would already be all but gone from the business world.)
>
> My employers are requiring me to learn Java because they've
> essentially decided that C++ is too complex to learn, too
> extendable and abusable to maintain, and too prone to
> portability problems. The last toehold left is that C++,
> carefully hand-coded and optimized, runs rings around
> Java in terms of performance. For me, 'final' is another
> way to justify C++ in a world which is starting to question
> why C++ is needed at all.
>

I am not aware of any evidence showing that final would improve the
performance of C++ programs. Are you?

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: allan_w@my-dejanews.com (Allan W)
Date: Tue, 17 Dec 2002 23:20:22 +0000 (UTC)
Raw View
fjh@cs.mu.OZ.AU (Fergus Henderson) wrote
> The original poster proposed three uses of "final":
>  (1) on classes, to prevent derivation
>  (2) on methods, to prevent overriding in derived classes
>  (3) on pointers, to prevent pointing to a derived class
>      (and likewise for references)
>
> Unfortunately with C++ syntax there would be a syntactic ambiguity
> with "final" on a method -- it could mean either (2) for the method,
> or it could mean (3) for the method's "this" pointer.

So, you would not only add "final" to the list of "cv-qualifiers"
(which I supose would now be "cvf-qualifiers"), but you would also
use them to overload calls to member functions?

    struct crazy {
        void foo();
        void foo() const;
        void foo() volatile;
        void foo() const volatile;
        void foo() final;
        void foo() const final;
        void foo() volatile final;
        void foo() const volatile final;
    };

Maybe it would be sufficient to allow it for pointers, but not to
overload on finality.

    struct sane { };
    struct less_sane { };
    final sane *s = new sane; // OK
    final less_sane *l = new less_sane; // OK
    final sane *t = new less_sane; // ERROR
    san *u = new less_sane; // OK

Could still use (2) to indicate that a particular function won't be
overridden (at least not without changing the name):

    struct { final void bar(); };

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Tue, 17 Dec 2002 23:20:24 +0000 (UTC)
Raw View
Allan W wrote:
>
> Pete Becker <petebecker@acm.org> wrote in message news:<3DFD127A.DAEBC78@acm.org>...
> > Scott Mayo wrote:
> > >
> > > I don't know of a hue and cry against 'final' in Java, though I suppose
> > > opponents could claim this is because final is so necessary (Java
> > > performs hideously without it) that it has ceased to be seen as evil.
> > >
> >
> > Java isn't C++. There are many things that Java has done that we
> > shouldn't emulate in C++.
>
> On the other hand, C++ shouldn't shy away from them just because Java
> already did them. This is not a competition.

Of course not. But the argument seems to be that since Java has final we
need it in C++.

>
> In Java, you use the "+" operator to add two integers. Should we change
> this for C++, just to be different?

Of course not.

> C++ did it before Java did; should
> we demand that the Java language change this, just for the sake of
> being different?

Of course not.

>
> It seems to me that Scott wasn't saying, "We should do whatever Java does."
> Instead, I think Scott was saying, "Here's a case where the keyword being
> debated was useful -- which proves that it CAN be useful.

If it's useful in Java that proves it is useful in Java. Transferring
that knowledge from Java to C++ requires a far more detailed analysis.
It requires understanding what it does in Java and why that's
beneficial, then determining whether the same issues are present in C++
and whether it would provide the same benefits.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: allan_w@my-dejanews.com (Allan W)
Date: Tue, 17 Dec 2002 23:20:33 +0000 (UTC)
Raw View
pdimov@mmltd.net (Peter Dimov) wrote in message news:<7dc3b1ea.0212170733.7d08ef9b@posting.google.com>...
> allan_w@my-dejanews.com (Allan W) wrote in message news:<7f2735a5.0212161806.1e64e9de@posting.google.com>...
> > pdimov@mmltd.net (Peter Dimov) wrote
> > > francis.glassborow@ntlworld.com (Francis Glassborow) wrote
> > > > Final would at least allow you to document that your classes and
> > > > templates will not work with final classes.
> > >
> > > I don't see how "final" would help me to write documentation.
> >
> > Please allow me to demonstrate. Here's the version without final:
> >
> >     struct shape {
> >         ~shape()=0;
> >         void draw() = 0;
> >         // ... etc ...
> >     };
> >     shape::~shape() {};
> >
> >     struct circle : public shape { // Do not derive from this class!
> >         circle(double center_x, center_y, radius);
> >         ~circle() {}
> >         void draw(); // Defined elsewhere
> >     };

I forgot the "virtual" keyword -- in the obvious places.

> [...]
>
> Thank you for the example. Here's how I would have written it:
>
> class shape
> {
> protected:
>
>    ~shape() {}
>
> public:
>
>    virtual void draw() = 0;
> };
>
> shared_ptr<shape> create_circle();
> shared_ptr<shape> create_rectangle();
> shared_ptr<shape> create_other();

I see. As far as I can tell, the big difference is that classes
circle, rectangle, and so on have internal (or no) linkage. You
would still have a function somewhere named circle::draw, right?

---
[ 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: alain@miniussi.net (Alain Miniussi)
Date: Tue, 17 Dec 2002 23:51:49 +0000 (UTC)
Raw View
Allan W wrote:

> alain@miniussi.net (Alain Miniussi) wrote
>> How do you fix the perf issue in C++ ? The only solution
>> I can think of (without final) implies global optimization
>> and no dynamic linking.
>
> Would you please elaborate on the perf(ormance?) issue?
>
> Are you pointing out that virtual function calls take longer than
> standard function calls?

The difference is usually small (well, that could be
argued, but I do not have access to machine were the difference
can be more important than usual so I'll drop it), but where you
have standard function call you can have inlining.

> If so, please perform some simple statistics
> and report back -- while the performance difference does exist, I
> think you might be surprised just how minor they are.

They can be minor or big depending on how you fake the benchmark,
(by the way, I did it, and was surprised of how big the difference
can be, thanks :).

> And remember
> that it happens only when you call a function virtually.

Which is the whole point, final help to detect that some call do not
have to be performed through the vtable.

Alain


** NONE ** vcall> time ./a.out

real    0m4.434s
user    0m4.390s
sys     0m0.010s
** NONE ** vcall> time ./a.out not virtual

real    0m0.028s
user    0m0.030s
sys     0m0.000s
** NONE ** vcall>

But then, who wants to return 42 100000000 times....

---
[ 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: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Wed, 18 Dec 2002 01:12:23 +0000 (UTC)
Raw View
allan_w@my-dejanews.com (Allan W) writes:

| fjh@cs.mu.OZ.AU (Fergus Henderson) wrote
| > The original poster proposed three uses of "final":
| >  (1) on classes, to prevent derivation
| >  (2) on methods, to prevent overriding in derived classes
| >  (3) on pointers, to prevent pointing to a derived class
| >      (and likewise for references)
| >
| > Unfortunately with C++ syntax there would be a syntactic ambiguity
| > with "final" on a method -- it could mean either (2) for the method,
| > or it could mean (3) for the method's "this" pointer.
|
| So, you would not only add "final" to the list of "cv-qualifiers"

I thought the rules on the combinaison of cv-qualifiers were already
complicated...

--
Gabriel Dos Reis,       gdr@integrable-solutions.net

---
[ 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: fjh@students.cs.mu.OZ.AU (Fergus Henderson)
Date: Wed, 18 Dec 2002 15:42:32 +0000 (UTC)
Raw View
petebecker@acm.org (Pete Becker) writes:

>Fergus Henderson wrote:
>>
>> Class hierarchy browsers generally don't catch template classes for which
>> there are no instantiations.  Also, they require that the program be
>> in a compilable state, which is often not the case during maintenance.
>
>In which case final won't help you, either.

Final *will* help here, because I can just add "final", and continue
on with the rest of my programming task.  I can be confident that my
invariants won't be broken.  If there are templates which violate those
invariants, I know that the problem will be detected at compile or link
time when those templates get instantiated, rather than resulting in
an error which is not detected until after the product has been shipped.
Likewise for code which has not yet been compiled yet because the
program was not in a compilable state.

--
Fergus Henderson <fjh@cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.

---
[ 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: pdimov@mmltd.net (Peter Dimov)
Date: Wed, 18 Dec 2002 15:42:33 +0000 (UTC)
Raw View
allan_w@my-dejanews.com (Allan W) wrote in message news:<7f2735a5.0212171519.6ae4ff42@posting.google.com>...
> pdimov@mmltd.net (Peter Dimov) wrote in message news:<7dc3b1ea.0212170733.7d08ef9b@posting.google.com>...
> >
> > Thank you for the example. Here's how I would have written it:
> >
> > class shape
> > {
> > protected:
> >
> >    ~shape() {}
> >
> > public:
> >
> >    virtual void draw() = 0;
> > };
> >
> > shared_ptr<shape> create_circle();
> > shared_ptr<shape> create_rectangle();
> > shared_ptr<shape> create_other();
>
> I see. As far as I can tell, the big difference is that classes
> circle, rectangle, and so on have internal (or no) linkage. You
> would still have a function somewhere named circle::draw, right?

Of course. Shape is abstract, so you can deduce that there are leaf
classes present, but you can't derive from them. ;-)

---
[ 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: pdimov@mmltd.net (Peter Dimov)
Date: Wed, 18 Dec 2002 15:42:45 +0000 (UTC)
Raw View
fjh@cs.mu.OZ.AU (Fergus Henderson) wrote in message news:<atmos6$qfs$1@mulga.cs.mu.OZ.AU>...
> pdimov@mmltd.net (Peter Dimov) writes:
>
>  >allan_w@my-dejanews.com (Allan W) wrote in message news:<7f2735a5.0212121624.33fa0b81@posting.google.com>...
>  >>
>  >> The real argument in favor of preventing derivation, seems to be that
>  >> not all classes have virtual destructors. Virtual destructors are
>  >> vitally important if the class is used polymorphically, [...]
>  >
>  >Not correct.
>  >
>  >class X
>  >{
>  >public:
>  >
>  >  virtual void f() = 0;
>  >
>  >protected:
>  >
>  >  ~X() {}
>  >};
>  >
>  >class impl: public X
>  >{
>  >public:
>  >
>  >  virtual void f() {}
>  >};
>  >
>  >boost::shared_ptr<X> px(new impl);
>
> I don't understand.  Won't that result in undefined behaviour
> when px's destructor is called?

No.

> See 5.3.5 paragraph 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.

Please note that ~X() is protected. You can't delete a pointer to X.

---
[ 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: pdimov@mmltd.net (Peter Dimov)
Date: Wed, 18 Dec 2002 15:42:48 +0000 (UTC)
Raw View
fjh@cs.mu.OZ.AU (Fergus Henderson) wrote in message news:<atmna7$p0o$1@mulga.cs.mu.OZ.AU>...
> pdimov@mmltd.net (Peter Dimov) writes:
> >francis.glassborow@ntlworld.com (Francis Glassborow) wrote:
> >> Peter Dimov <pdimov@mmltd.net> writes
> >> >In the absence of documentation explicitly saying "though shalt not
> >> >derive", derivation from a class is perfectly legal, and not a bug.
> >> >You must not diagnose it. How many of your classes make that claim in
> >> >their documentation? My guess is that none do, and this is exactly as
> >> >it should be, since derivation is not a mistake by itself.
> >>
> >> And that is exactly what Fergus et al. have been challenging. Sometimes
> >> derivation can be a mistake by itself because the class
> >> designer/implementor knows that the class needs to make assumptions
> >> about pointers and references that would be broken if they happened to
> >> point/refer to an instance of a derived type.
> >
> >Not correct. Derivation is almost never a mistake in itself, and the
> >posted example did not demonstrate a case where it is a mistake. The
> >swap member function would always work as intended. In some cases it
> >would leave a derived class in an inconsistent state, but the meaning
> >of "inconsistent" is defined by the design of the derived class and
> >not by the fact that it has been derived.
>
> Your statement "The swap member function would always work as intended"
> is wrong.  The "swap" member function would not work as intended if
> passed an object of a derived class with additional data members.  The
> intended meaning of "swap" is that it swap the values of the two objects.
> If passed an object of the derived class, it does not have that effect.

"swap" will correctly swap the values of the two objects. The fact
that it the argument is a subobject, and not a complete object, is of
no concern to "swap" itself. If you replace inheritance with
containment and invoke "swap" on the member, the effect would be the
same; you can't blame inheritance for "swap"'s alleged failure,
although you _could_ blame the sometimes undesirable derived to base
conversion.

> However, you're right that it's not the derivation alone that causes the
> problem; it's derivation, plus passing a derived class object to the
> swap member function,

Plus the fact that the derived class is broken when the base part is
modified. Many derived classes don't break in such situations. The
derived class may have no state, or it may have state that is
independent of the state of the base class.

> and then relying on the post-condition of the
> swap member function.

What is the postcondition of swap?

> Clearly it must be OK to rely on the post-condition of a function that
> you've called.  All of our programming relies on that.  So that only
> leaves two things which could be wrong: the derivation, or passing
> the derived class object to the swap member function.

True. But even if you blame the derivation (and this is too strict as
the user may never call swap), not all possible derivations are wrong.

> The original poster proposed three uses of "final":
>  (1) on classes, to prevent derivation
>  (2) on methods, to prevent overriding in derived classes
>  (3) on pointers, to prevent pointing to a derived class
>      (and likewise for references)

I have already shown how you can implement (3) in current C++: use a
template, and a static assertion. It doesn't cover all cases, but
neither would (3), unfortunately.

void f(X final const & x);

void g(X const & x) { g(x); }

g(Y());

To get back to our "swap" problem, the problem is real. The 'std::
overloads' part of

http://std.dkuug.dk/JTC1/SC22/WG21/docs/papers/2001/n1296.htm

includes two examples that demonstrate the same pitfall. Note that the
standard declaration of std::swap minimizes the possibility of error
since it doesn't accept arguments of different types. This was one of
the motivations for the "function template partial specialization"
proposal as template specializations retain the interface of the
original template.

---
[ 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, 18 Dec 2002 16:12:53 +0000 (UTC)
Raw View
Alain Miniussi wrote:
> So, you tell me, how high is the price of a virtual call ? :-)
> Compared to say, an inlined function ? (if it's final it can
> be inlined).
> With "final", I can adapt.

Once you have profiled your code and determined that a
particular virtual call is the problem, and at the call
site you know what class you actually have, you can
replace that call with p->Class::func() and bypass the
virtual mechanism.

---
[ 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, 18 Dec 2002 16:16:00 +0000 (UTC)
Raw View
Allan W wrote:
> It seems to me that Scott wasn't saying, "We should do whatever Java does."
> Instead, I think Scott was saying, "Here's a case where the keyword being
> debated was useful -- which proves that it CAN be useful. That doesn't mean
> that this keyword is the only way to do it -- but it does work, so please
> consider that as you deliberate about using it yourselves."

What we objectors are saying is that just because a
buggy whip makes a horse-drawn cart go faster, that
doesn't mean that automobiles should come equipped
with one. The fact is that 'final' in Java solves
a problem that C++ doesn't have, so there is no use
applying the Java prior art to C++. If 'final' is
to be a part of C++, then a significant need for
it in C++ must be demonstrated.

---
[ 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: kanze@gabi-soft.de (James Kanze)
Date: Wed, 18 Dec 2002 17:09:50 +0000 (UTC)
Raw View
llewelly.@@xmission.dot.com (llewelly) wrote in message
news:<86el8hjkcw.fsf@Zorthluthik.foo>...
> kanze@gabi-soft.de (James Kanze) writes:
> [snip]

> Your mention of using a 'final'-like feature to preserve class
> invariants is the first I've heard of it. I'm going out on limb here,
> but I strongly suspect most of those supporting final have not thought
> of preserving class invariants, and are trying to solve a quite
> different problem, which your suggestion does not address. (I agree
> that the problem you describe is real, and could be solved by the
> mechanism you suggest - I just think most of the other posters here
> are not thinking about it when they think of 'final'.)

What other use could it have in C++?

I base my comments on my experience in Java -- in user code, all of the
use we made of final was to preserve class invariants.  And it is
interesting to note that well over half of our functions were declared
final.  The situation is less critical in C++, because most of the
functions we declared final were in the base class, and wouldn't be
virtual in C++.  (We basically used the now standard idiom for ensuring
pre- and post-conditions, with all of the functions in the public
interface declared final.)  Still, there are many cases where it would
help.

The only other use I've seen of final in Java is for protection, when
two classes share resources.  The obvious example (in Java) is String
and StringBuffer; for performance reasons, when a StringBuffer is
converted to a String, the new String acquires the physical buffer from
the StringBuffer, where it is marked as copy-on-write.  In C++, the
obvious solution would be to make the two classes friends of one
another.  In Java, there aren't any friends, and the solution adopted
was to use package scope.

> By use of such things as non-virtual destructors, assignment
>     operators, swap members, cast operators, etc, it is possible to
>     create a class (call it Base) such that a class Derived which is
>     derived from Base has some error-prone behavior when used
>     polymorphicly. The classic example is deleteing an object with a
>     non-virtual destructor, using a pointer that is not of the
>     object's exact type. I believe these kinds of classes are in fact
>     the primary bone of contention between the want-finals and the
>     not-want-finals.

I want final, but I don't see any real problem here.

Obviously, it is a good thing to be able to detect misuse of a class.
Practically, we won't ever be able to detect every misuse, and the
actual frequency of deriving when not appropriate seems rather low.

Before this thread, I'd have probably said OK to a final blocking
inheritance anyway; several posters, however, have show important idioms
involving derivation (for other reasons that the usual isA relationship)
from arbitrary classes (or event types? -- maybe the rules should be
extended to allow derivation from the basic types).  Given this, I would
argue against blocking these idioms (even though I don't currently use
them) just to catch some errors which are, statistically speaking, rare.

But I'm left with the problem of ensuring class invariants.  And that is
important, at least to me.  As I said, in Java, I ended up declaring
most functions final.

A typical case of where it is important to declare a virtual function
final is when the implementation of an interface uses the template
pattern.  Because of the template pattern, the implementation class will
be a base class for further derivation.  The implementation overrides
the virtual function in the interface, and provides a new set of virtual
functions for the further derived classes to override.  The further
derived class should NOT, however, override the functions declared in
the base interface.

This particular case occurred three or four times in my last Java
application.

> Those who do not want final insist they can write classes with
>     non-virtual destructors, etc, which can be safely derived from, and
>     fulfill important needs. They will insist one can derive safely
>     from these clases, and they will insist one can use them
>     safely. If you look over the boost source code - you will see they
>     are correct to insist these things can be done safely and
>     usefuly. If you read the appropriate literature - you will see why
>     they think all 'good programmers' should know how to use these
>     constructs.

Certainly.  I wasn't aware of these idioms before this discussion, but I
would agree that they shouldn't be banned.

> Those who want final insist base classes with non-virtual destructors,
>     assignment operators, ill-designed cast operators, etc, are an
>     important source of errors; they believe that many programmers do
>     not read the literature which tells them how to make such things
>     as bases with non-virtual destructors safe and useful, they
>     believe that not everyone remembers everything they read, and
>     finally that programmers are failible human beings, who might
>     benefit from additional error checking.

> The problem is that both sides, as far as I can see - are correct. Yes,
>     inheritance can be misused, and a sanity check on inheritance can
>     prevent real errors. And yes, it would be all too easy for a
>     misused sanity check to prevent the use of vital inheritance-based
>     idioms.

In the end, I like Pete Becker's position: I want to prevent things
which can break MY code, but my client's code is his responsibility.
This is overstated: if I can easily trap some stupid client errors, so
much the better.  But it shouldn't come at the price of preventing some
valid uses.

Maintaining class invariants is essential in order to avoid breaking my
code.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Wed, 18 Dec 2002 17:12:42 +0000 (UTC)
Raw View
In article <3DFF87F6.ABD9DB1D@acm.org>, Pete Becker <petebecker@acm.org>
writes
>Francis Glassborow wrote:
>>
>> In article <3DFE7645.DA05A56E@acm.org>, Pete Becker <petebecker@acm.org>
>> writes
>> >Java practices are not prior art for C++, although they might be
>> >considered prior graffiti. Java is a different language with different
>> >design goals and a different runtime environment. Even if final is good
>> >in Java that doesn't say anything about its utility in C++.
>>
>> But WG21 frequently considered that what had been done in other
>> languages was prior art. You may disagree that that is a correct view of
>> prior art,  but it is your opinion rather than fact.
>>
>
>It is my opinion that merely pointing out that some other language has
>some feature does not justify adding that feature to C++. Is that also
>your opinion?

Of course it does not justify adding the feature to C++ but it does
allow us to look at another languages experience with it and consider
how relevant the feature would be to C++. Note how different that is to
such features as namespaces and templates where relevant third party
experience was fairly obscure.


--
Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ 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: kanze@gabi-soft.de (James Kanze)
Date: Wed, 18 Dec 2002 17:12:51 +0000 (UTC)
Raw View
allan_w@my-dejanews.com (Allan W) wrote in message
news:<7f2735a5.0212171519.6ae4ff42@posting.google.com>...
> pdimov@mmltd.net (Peter Dimov) wrote in message
> news:<7dc3b1ea.0212170733.7d08ef9b@posting.google.com>...
> > allan_w@my-dejanews.com (Allan W) wrote in message
> > news:<7f2735a5.0212161806.1e64e9de@posting.google.com>...

    [...]
> > shared_ptr<shape> create_circle();
> > shared_ptr<shape> create_rectangle();
> > shared_ptr<shape> create_other();

> I see. As far as I can tell, the big difference is that classes
> circle, rectangle, and so on have internal (or no) linkage. You would
> still have a function somewhere named circle::draw, right?

There are several big differences:

  - He is imposing that the object be managed by a shared_ptr -- this
    may not be appropriate for the user:-).  This is a minor matter, and
    can easily be fixed (and in application level code, may not need
    fixing).

  - He is imposing that all instances be allocated on the heap.  And
    that IS an important restriction.

  - He effectively prevents the derived class from offering an extended
    interface.  What happens if I want to offer some special additional
    functionality in circle, for the case where the user knows he has a
    circle?

  - Practically speaking, none of the client functions in the derived
    class can be inline.  I don't like it when profiling tells me I have
    to change an interface.

The last two can really be summed up by the fact that he has thrown away
type information in the return value.  This could be alleviated by
having create_circle() return a circle*, rather than a shape*.  But this
is only usable *if* the client can see the definition of circle, which
sort of defeats the purpose.

The idiom is useful in some cases.  It is probably appropriate in this
particular case.  But it isn't appropriate everywhere, and it isn't a
general answer to the problem.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Wed, 11 Dec 2002 03:40:59 +0000 (UTC)
Raw View
Nicolas Fleury wrote:
>
> Pete Becker wrote:
> >
> > That has nothing to do with Francis' question or with mine. Let me
> > repeat mine:
> >
> > What concrete evidence is there that being able to prevent inheritance
> > improves program quality?
> >
>
> Suppose for example your have a class A and a derived class B.  The way
> B is designed, it should not be derived and you document that.  You
> provide a container of A.  Somebody doesn't see the documentation and
> derive a class C from B.  After, someone comes to you and tell you your
> container of A is buggy (because there's some C objects in it).
>

Yes, there are many hypothetical examples. No, this is not concrete
evidence.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: pdimov@mmltd.net (Peter Dimov)
Date: Wed, 11 Dec 2002 03:47:18 +0000 (UTC)
Raw View
fjh@cs.mu.OZ.AU (Fergus Henderson) wrote in message news:<at1pkf$pd4$1@mulga.cs.mu.OZ.AU>...
>
> Why should the bar be set higher for this feature than for other C++
> features?

It is not.

"final" is being marketed to library designers as it supposedly would
be useful to them. Library designers aren't buying. Sorry. ;-)

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Wed, 11 Dec 2002 03:58:01 +0000 (UTC)
Raw View
Fergus Henderson wrote:
>
> petebecker@acm.org (Pete Becker) writes:
>
> >Unless you're the user's mother it's not
> >your responsibility to try to make him into a better programmer.
>
> It is every class designer's responsibility to do their best
> to ensure that the classes that they design are easy to use,
> and hard to misuse.
>

Yup. And we all love the flag, mom, and apple pie. But slogans don't
create good designs; good designers do. If Joe Programmer in East
Oshkosk wants to use your class but can't because you've blocked
inheritance then your class isn't easy to use.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Wed, 11 Dec 2002 04:09:16 +0000 (UTC)
Raw View
Fergus Henderson wrote:
>
> Furthermore, no programmer can read documentation that has not yet been
> written.  But "final" can still be useful in such cases.

I see. This is a replacement for good documentation.

> For example,
> suppose your program has an Array class, and you want to add a swap()
> method to it, which won't work if passed a class derived from Array
> (as in the example in my earlier post).

I saw where you said that, but saying it doesn't make it true.

> If the Array class is used in
> a large number of places, it may be difficult to determine whether there
> is any code which derives from Array.

grep is your friend.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Wed, 11 Dec 2002 04:15:24 +0000 (UTC)
Raw View
nid_oizo@yahoo.com_removethe_ (Nicolas Fleury) writes:

[...]

| C++ is a language that provides many features to detect errors at
| compile-time instead of at run-time.  A final-like feature seems to me
| suitable for C++.

I think that argument can be made for *any* proposed feature for
addition to C++.  I think, a key issue is whether C++ should just be a
collection of features.  In other words, does the proposed feature
usefulness outweights possible downside?

--
Gabriel Dos Reis,       gdr@integrable-solutions.net

---
[ 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: scottm@toast.net (Scott Mayo)
Date: Wed, 11 Dec 2002 04:46:52 +0000 (UTC)
Raw View
> It is, indeed, one of the roles of a government to provide rules for the
> safety of its citizens. Writing a class doesn't make a programmer into a
> government.

I think this is the basis of the disagreement, and why I think futher debate
isn't really fruitful. Some of us have spent the last thirty years working
out that there are good programmers and bad programmers; and
that one of the functions of the functions of good programmers is
to create code that bad programmers cannot do vast damage with.
It's enlightened self-interest - as long as the performance of the
unskilled programmers has an effect on the same bottom line
that generates my paycheck, I'll do what I can to keep them out
of the briers.

I'll give an example. It's not uncommon to write functions that
check their arguments and return an error code of some sort if
bad values are passed. I've stopped doing this as regards
checking for illicit NULL pointers, and in some other circumstances.
Seem strange? It isn't: it's based on years of experience. People
don't check for error codes, so returning them is too often pointless.
But dereferencing NULL pointers on unix systems raises SEGV,
which is a *far* more effective way to indicate a problem. Anyone can
ignore an error code, but it's hard to ignore a core dump. And a core
dump tells you what went wrong where. Shipped bugs have decreased
since I took this approach.

In general and IMHO, the best approach is the one that points
up errors the fastest and most clearly. Compiler errors and warnings
do this: there's nothing like code that, in self-defense, will not
compile when mishandled. C++ took great strides in this
direction. Show me any feature that will catch a mistake
before the code runs, and I want it. Show me a technique
that makes finding bugs in compiled code easier and faster
and I'm likely all for it. And if that makes me a government,
then welcome to my benevolent dictatorship.



---
[ 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: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Wed, 11 Dec 2002 14:29:19 +0000 (UTC)
Raw View
In article <7dc3b1ea.0212100455.78c14150@posting.google.com>, Peter
Dimov <pdimov@mmltd.net> writes
>fjh@cs.mu.OZ.AU (Fergus Henderson) wrote in message news:<at1pkf$pd4$1@mulga.cs.mu.OZ.AU>...
>>
>> Why should the bar be set higher for this feature than for other C++
>> features?
>
>It is not.
>
>"final" is being marketed to library designers as it supposedly would
>be useful to them. Library designers aren't buying. Sorry. ;-)

You speak for all library designers? If the proponents of final are not
library designers what are they?

No library designer would be compelled to use final were it available.
Instead of  a resolute no to consideration of final why not get a couple
of compilers to implement it and gain some experience? Unlike most
extensions this is one that we would not have a problem with removing
from code that made use of it because it would just revert to the
current position.

While I am often suspicious of vendor provided extensions (because of
vendor lock-in) this is one (perhaps named _final) that I would like to
see tried by a couple of major implementors.

By the way, there seems to be confusion in some peoples minds as to what
this is being applied to. I am not interested in finalisation of virtual
methods and finalisation of virtual bases is both confusing and not a
feature that could be tried and then removed (without cost). What I am
in favour of (and I think quite a few others are) is the ability to
declare that a class is a 'leaf class', i.e. cannot be used as a base
class.

--
Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ 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: terekhov@web.de (Alexander Terekhov)
Date: Wed, 11 Dec 2002 14:47:54 +0000 (UTC)
Raw View
Francis Glassborow wrote:
[...]
> What I am in favour of (and I think quite a few others are) is the
> ability to declare that a class is a 'leaf class', i.e. cannot be
> used as a base class.

Do you have an example of such ``'leaf class', i.e. CANNOT be used as
a base class.'' [emphases added]. TIA.

regards,
alexander.

---
[ 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: pdimov@mmltd.net (Peter Dimov)
Date: Wed, 11 Dec 2002 14:48:08 +0000 (UTC)
Raw View
kuyper@wizard.net ("James Kuyper Jr.") wrote in message news:<3DF49DB7.3010405@wizard.net>...
>
> By your own arguments, documenting what shouldn't be done should be
> sufficient. That argument applies equally well (or more accurately,
> "equally poorly") to final, private/protected, and const. In all three
> cases, the feature prevents people from having the option of doing
> something that could make your code break when they use it. In all three
> cases, the feature would never be needed if the applicable restrictions
> were correctly documented, and if that documentation was read,
> understood, and infallibly obeyed.

Not really.

When you make something "private", you are helping users catch their
own mistakes. A "private" member is not documented. You don't say
"this class has a private member of type int named count; don't touch
it." Any code that even mentions the name of "count" is buggy; there
is no logical "count" in the class, although this particular
version/implementation might contain a physical "count".

It's the same with const. Any code that attempts to modify a const
reference returned by the class is buggy by default. You don't need
any documentation. The implicit contract that the class is free to
return a reference to a genuinely const object is enough.

In the absence of documentation explicitly saying "though shalt not
derive", derivation from a class is perfectly legal, and not a bug.
You must not diagnose it. How many of your classes make that claim in
their documentation? My guess is that none do, and this is exactly as
it should be, since derivation is not a mistake by itself.

---
[ 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: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Wed, 11 Dec 2002 15:52:22 +0000 (UTC)
Raw View
In article <3DF74D90.61FACDA7@web.de>, Alexander Terekhov
<terekhov@web.de> writes
>
>Francis Glassborow wrote:
>[...]
>> What I am in favour of (and I think quite a few others are) is the
>> ability to declare that a class is a 'leaf class', i.e. cannot be
>> used as a base class.
>
>Do you have an example of such ``'leaf class', i.e. CANNOT be used as
>a base class.'' [emphases added]. TIA.

You miss the point. At the moment it is tortuous to ensure that the leaf
class CANNOT be used as a base class even when the designer specifies
that it should not be.

Why should a class designer require such a restriction? Consult your
lawyers. I did. If there is a way to prevent abuse that you fail to take
then you might be held responsible for the consequences (there is such a
mechanism, if tortuous)

When my gas appliances were being checked several years ago as part of
an annual maintenance check the responsible engineer disconnected one of
my fires because the law with regard to flues for burnt gases had been
changed. Had he not disconnected my fire he would have been legally
liable for all the consequences.

Why is it so hard for programmers to understand that we sometimes need
ways to disconnect things or be liable for the consequences.

--
Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ 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: Pete Becker <petebecker@acm.org>
Date: Wed, 11 Dec 2002 10:05:49 CST
Raw View
Allan W wrote:
>
> > > Pete Becker <petebecker@acm.org> wrote:
> > > > The programmer is in a better position to know what he needs than the
> > > > author of the class. Writing a class shouldn't turn you into a nanny.
>
> > Niklas Matthies wrote:
> > > Why not? It's your class, after all.
>
> petebecker@acm.org (Pete Becker) wrote
> > Yup, that's the bottom line, isn't it? Doesn't what users want; you
> > wrote it, you decide what others can do with it.
>
> Can I assume that your work at Dinkumware is neither in design nor
> in sales?

You can assume whatever you want.

>
> Personally, my own philosophy about software creation has been: give
> my clients/users/customers what they want, and be sure it works.
>

I think you've misunderstood what I said: that's exactly what I meant.
Blocking inheritance creates barriers for knowledgeable programmers.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "P.J. Plauger" <pjp@dinkumware.com>
Date: Wed, 11 Dec 2002 10:06:44 CST
Raw View
"Allan W" <allan_w@my-dejanews.com> wrote in message
news:7f2735a5.0212091743.52dec8a5@posting.google.com...

> > > Pete Becker <petebecker@acm.org> wrote:
> > > > The programmer is in a better position to know what he needs than the
> > > > author of the class. Writing a class shouldn't turn you into a nanny.
>
> > Niklas Matthies wrote:
> > > Why not? It's your class, after all.
>
> petebecker@acm.org (Pete Becker) wrote
> > Yup, that's the bottom line, isn't it? Doesn't what users want; you
> > wrote it, you decide what others can do with it.
>
> Can I assume that your work at Dinkumware is neither in design nor
> in sales?

A remarkably snarky ad hominem remark. Pete Becker does quite a bit of
design work for Dinkumware, and he's rather good at it. He also is
very helpful when assisting in sales efforts, but that's not his
principal job here.

> Personally, my own philosophy about software creation has been: give
> my clients/users/customers what they want, and be sure it works.

Motherhood and apple pie. And yet much of this discussion seems to be
about *preventing* users from doing something *you* don't want them
to do. For their own good, presumably.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: allan_w@my-dejanews.com (Allan W)
Date: Wed, 11 Dec 2002 10:07:23 CST
Raw View
petebecker@acm.org (Pete Becker) wrote
> How many program failures do you know of that have resulted from
> inappropriate inheritance and could have been prevented by blocking
> inheritance?

I worked on one project where inappropriate inheritance didn't cause
it to fail, but caused frustrations. The base class was a "resource"
as in a person or tool needed to do a job, and the derived class was
an employee. On the face of it, this seems to be an IS-A relationship,
but it isn't -- there's too many things that a resource can do but
an employee cannot. By the time I started to convince people that
inheritance wasn't a win here, too much code was already depending on
it -- it was effectively "chisled in stone" and will never be changed.

However, this was not a case of one lone programmer deciding to use
some existing class for derivation. (This was before I got there.)
Both classes were written by the same person, at the same time. If
there had been a keyword to block further inheritance, it would not
have been used. And no, this person never read the book "Effective C++."

I have since left that company. Several years after I realized that
this relationship was not appropriate, I'm almost certain that it
continues to exist.

---
[ 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: "Risto Lankinen" <rlankine@hotmail.com>
Date: Wed, 11 Dec 2002 10:09:10 CST
Raw View
Hi!

"Pete Becker" <petebecker@acm.org> wrote in message
news:3DF5382E.3D45AD33@acm.org...
>
> There's a great deal of history showing that access protection improves
> code quality.

Isn't finality a prime example of access protection???

Cheers!

 - Risto -


---
[ 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: pdimov@mmltd.net (Peter Dimov)
Date: Wed, 11 Dec 2002 16:10:37 +0000 (UTC)
Raw View
rmaddox@isicns.com (Randy Maddox) wrote in message news:<8c8b368d.0212090656.1977b7e2@posting.google.com>...
>
> Exactly so.  The designer of the class knows what assumptions they are
> making, and if one of those assumptions is that the class will not be
> derived from then that will impact the class design.

Not correct. The ability to know that the class will never be derived
from does not affect design.

> That is, a class
> that is intended to be used as a base class is explicitly designed
> differently, using different assumptions, than a class that is
> designed as a base class.

Correct. It is typically made abstract, for instance.

> Not every class is intended, designed, or
> even necessarily safe to be used as a base class.

Correct.

> No one has argued against that last statement, at least not as far as
> I can tell, and yet several have argued very strongly that compiler
> support for the concept of a class not intended to be derived from is
> somehow very wrong.  I am at a loss to grasp the counter argument.  If
> some classes really are best designed as leaf classes with no further
> inheritance, then why is compiler support for this a bad thing?

It's pretty simple, really.

The pro-final argument is that a good designer should utilize final in
order to produce better designs. Some of us believe that this is not
so.

- As a class designer, I don't think that final would enable me to
produce better designs. (It will not make my job easier.)

- As a library designer, I value the ability to use inheritance as an
implementation detail. Some libraries that currently work perfectly
well will break when fed final classes. (It will make my job harder.)

- As an user, I see little use of final. (It will not make my job
easier.)

- As an user of final classes, I don't expect to be "saved" from any
mistakes. (It will not make my job easier.)

- As an user, I think that final will be overutilized, as this thread
has demonstrated. (It will make my job harder.)

Net impact: negative. It will make my job harder.

---
[ 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: kuyper@wizard.net ("James Kuyper Jr.")
Date: Wed, 11 Dec 2002 16:09:58 +0000 (UTC)
Raw View
Pete Becker wrote:
> Fergus Henderson wrote:
>
>>petebecker@acm.org (Pete Becker) writes:
....
> create good designs; good designers do. If Joe Programmer in East
> Oshkosk wants to use your class but can't because you've blocked
> inheritance then your class isn't easy to use.

That's the purpose of this feature, to make it hard for Joe Programmer
to use the class this way. That's because such use would constitute
mis-use of the class. If that's not the case, then the class shouldn't
be marked 'final'.

---
[ 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: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Wed, 11 Dec 2002 16:13:24 +0000 (UTC)
Raw View
In article <7dc3b1ea.0212110636.6cdedf5e@posting.google.com>, Peter
Dimov <pdimov@mmltd.net> writes
>In the absence of documentation explicitly saying "though shalt not
>derive", derivation from a class is perfectly legal, and not a bug.
>You must not diagnose it. How many of your classes make that claim in
>their documentation? My guess is that none do, and this is exactly as
>it should be, since derivation is not a mistake by itself.

And that is exactly what Fergus et al. have been challenging. Sometimes
derivation can be a mistake by itself because the class
designer/implementor knows that the class needs to make assumptions
about pointers and references that would be broken if they happened to
point/refer to an instance of a derived type.


--
Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ 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: terekhov@web.de (Alexander Terekhov)
Date: Wed, 11 Dec 2002 16:56:23 +0000 (UTC)
Raw View
Francis Glassborow wrote:
[...]
> Why is it so hard for programmers to understand that we sometimes need
> ways to disconnect things or be liable for the consequences.

Ah, now I see. Uhmm. What about pay-per-inheritance "tags"/support [in
addition to final-thing], then? Don't know about you, but personally I
desperately need it.

regards,
alexander.

---
[ 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, 11 Dec 2002 18:22:49 +0000 (UTC)
Raw View
Francis Glassborow wrote:
> Why is it so hard for programmers to understand that we sometimes need
> ways to disconnect things or be liable for the consequences.

I believe that this argument is nonsensical
for what is being discussed. If not, then I
don't know how anyone can feel comfortable
serving on a language standards committee.
given the permissiveness of the results. Any
implementor of std::vector with an operator[]
that doesn't call vector::at should be hauled
into court!

---
[ 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, 11 Dec 2002 18:22:55 +0000 (UTC)
Raw View
James Kuyper Jr. wrote:
> That's the purpose of this feature, to make it hard for Joe Programmer
> to use the class this way. That's because such use would constitute
> mis-use of the class. If that's not the case, then the class shouldn't
> be marked 'final'.

The rest of us are afraid that Joe Programmer is the one marking.

---
[ 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: nid_oizo@yahoo.com_removethe_ (Nicolas Fleury)
Date: Wed, 11 Dec 2002 18:47:13 +0000 (UTC)
Raw View
Pete Becker wrote:
> Nicolas Fleury wrote:
>
>>Pete Becker wrote:
>>
>>>That has nothing to do with Francis' question or with mine. Let me
>>>repeat mine:
>>>
>>>What concrete evidence is there that being able to prevent inheritance
>>>improves program quality?
>>>
>>
>>Suppose for example your have a class A and a derived class B.  The way
>>B is designed, it should not be derived and you document that.  You
>>provide a container of A.  Somebody doesn't see the documentation and
>>derive a class C from B.  After, someone comes to you and tell you your
>>container of A is buggy (because there's some C objects in it).
>>
>
>
> Yes, there are many hypothetical examples. No, this is not concrete
> evidence.

Well, this is not hypothetical, a similar example has happened to me...
  But what do you mean exactly by concrete evidence then?  Could you
give an example of a concrete evidence for another C++ feature?  Thx.

Regards,

Nicolas

---
[ 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: pdimov@mmltd.net (Peter Dimov)
Date: Mon, 9 Dec 2002 00:36:07 +0000 (UTC)
Raw View
petebecker@acm.org (Pete Becker) wrote in message news:<3DF14A6E.4096445@acm.org>...
> Randy Maddox wrote:
> >
> > I also firmly agree with James Kuyper and others who state that the
> > designer of a class is in a position to know better whether or not
> > his/her class should be derived from.
>
> Nobody has disputed this.

For the record, I do dispute this claim. The designer knows whether
the class has been designed for inheritance. The user knows whether,
in a particular context, derivation from the class is necessary (or
the best alternative) in order to accomplish the task at hand.

Of course one could argue that the user must not be trusted as it is
likely that he is incompetent.

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Mon, 9 Dec 2002 00:39:46 +0000 (UTC)
Raw View
"James Kuyper Jr." wrote:
>
> Pete Becker wrote:
> ....
> > I've said three times now that it does not apply to private/protected
>
> Yes, you have.
>
> > and why.
>
> I missed that; at least, I never saw you draw the distinction in any way
> that actually worked.
>
> You mentioned the distinction between what's needed to make your code
> work, and what's needed to make other people's code work.

No, what I said was that the distinction is between "my code won't work
right if you do this" and "your code won't work right if you do this."
It's not simply about making code work, it's about allocating
responsibility for making it robust.

> That's not a
> very clear distinction, since the whole issue only arises when both sets
> of code have to work together.

It arises when you design and implement a class.

> In any event, to the extent that the
> distinction is clear, private/protected very clearly comes down on the
> other side of fence; just like 'final', it's NEVER needed to make your
> own code work.
>

When you write a class you define its interface, and you specify a set
of class invariants. The interface always preserves the class
invariants. If allowing access to a piece of member data permits
breaking the class invariants then you make it private. Otherwise you
leave open the possibility that uses will do something that prevents
your code from working right.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kuyper@wizard.net ("James Kuyper Jr.")
Date: Mon, 9 Dec 2002 01:02:16 +0000 (UTC)
Raw View
Pete Becker wrote:
> Randy Maddox wrote:
>
>>I also firmly agree with James Kuyper and others who state that the
>>designer of a class is in a position to know better whether or not
>>his/her class should be derived from.
>
>
> Nobody has disputed this.

Yes you have; you've asked:

"Why do you think you're better qualified to judge the code that someone
else is writing than they are?"

The answer: "Because I designed the class that their code is trying to
mis-use!"


---
[ 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: petebecker@acm.org (Pete Becker)
Date: Mon, 9 Dec 2002 01:05:12 +0000 (UTC)
Raw View
Francis Glassborow wrote:
>
> In article <3DF147AE.855D4F9C@acm.org>, Pete Becker <petebecker@acm.org>
> writes
> >I take it you don't ever cross the street, because, after all, some
> >drunk driver might come screeching around the corner and run you down.
>
> If you will argue from analogy, many countries have laws about
> jay-walking and require that you only cross roads at authorised crossing
> points (they do not trust their citizens to know when it is OK to cross
> at a place of their choosing).
>
> Arterial roads usually have complete prohibitions against pedestrians
> crossing them (you have to use a footbridge or an underpass.
>
> Many places have barriers where footpaths join sidewalks to prevent the
> careless pedestrian from overshooting the join and finishing up in the
> path of oncoming traffic.
>
> Of course pedestrians should read signs, but we know they do not always
> do so.
>

It is, indeed, one of the roles of a government to provide rules for the
safety of its citizens. Writing a class doesn't make a programmer into a
government.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Mon, 9 Dec 2002 01:09:02 +0000 (UTC)
Raw View
In article <3DF27F8B.9F19651F@acm.org>, Pete Becker <petebecker@acm.org>
writes
>class Array
>{      // sketch only, of course
>public:
>       void append(int value) { data[count++] = value; }
>private:
>       int *data;
>       int count;
>};
>
>Now, the reason you make 'count' private is that if it's public user
>code can modify count in unpredictable ways, and then append will not do
>what it is supposed to do.

But any responsible programmer who has read the documentation would not
do that. So your arguments against 'final' are equally valid here. Why
should a programmer be so arrogant as to prevent me from accessing data
directly when I know it is OK?

I suspect that you would be defending  'final'  had it been in the
original design of C++.

I also note that proponents have suggested that 'final' should be
overridable but only by deliberate action. I think that is a sane
compromise. We spend far too many hours trying to deal with the results
of implicit behaviour (conversions, generated copy semantics etc.) to be
unaware of the costs.

The only arguments that I would accept against providing 'final' + a
mechanism for over-riding it would be that its implementation had
serious impact on the semantics of C++.


--
Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Mon, 9 Dec 2002 01:10:00 +0000 (UTC)
Raw View
"James Kuyper Jr." wrote:
>
> Pete Becker wrote:
> > "James Kuyper Jr." wrote:
> >
> >>Pete Becker wrote:
> >>
> >>>Tom Hyer wrote:
> >>>
> >>>
> >>>>petebecker@acm.org (Pete Becker) wrote in message news:<3DED8110.6FF05730@acm.org>...
> >>>>
> >>>>
> >>>>>The distinction to keep in mind is that between "if you do this my code
> >>>>>won't work" and "if you do this your code won't work." The former is why
> >>>>>you make things private. The latter is not your responsibility.
> >>>>>
> >>>>
> >>>>   But the former is never a reason to make something private.
> >>>>
> >>>
> >>>
> >>>Nonsense. That is exactly what private is for.
> >>
> >>Can you provide an example? I can't remember ever using it for that
> >>purpose, and I don't see how it could be used for that purpose.
> >>
> >
> >
> > class Array
> > {     // sketch only, of course
> > public:
> >       void append(int value) { data[count++] = value; }
> > private:
> >       int *data;
> >       int count;
> > };
> >
> > Now, the reason you make 'count' private is that if it's public user
> > code can modify count in unpredictable ways, and then append will not do
> > what it is supposed to do.
>
> Which is needed only to make other people's code work. It doesn't make
> your code work, because even if 'count' weren't private, you'd never do
> something as stupid as changing 'count' from outside the append()
> member.

Okay, it's clear that your goal is to disagree, not to understand.
There's no point in continuing this discussion.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Mon, 9 Dec 2002 01:16:49 +0000 (UTC)
Raw View
"James Kuyper Jr." wrote:
>
> Pete Becker wrote:
> ....
> > Once again: the difference is between "my code won't work right if you
> > do this" and "your code won't work right if you do this." You use
> > private to enforce the first of these. The second is not your
> > responsibility.
>
> Surely you have 'first' and 'second' reversed? Can you show me any way
> in which 'private' makes your own code work? As far as I can see, its
> sole purpose is to make sure that other people's code works, by ensuring
> that their code doesn't have inappropriate access to your class. Your
> own code will never even attempt to make inappropriate access to your
> class. Your in-class code isn't even affected by 'private'. Your out of
> class code is written by the author of the class, and if there's anyone
> who understands the limitations of your class better than you, there's a
> serious problem somewhere.
>

If youblet users arbitrarily change the contents of your class then the
code you wrote to implement your class won't work right.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Mon, 9 Dec 2002 01:18:04 +0000 (UTC)
Raw View
Niklas Matthies wrote:
>
> What exactly is the fundamental difference you seem to see, that goes
> beyond an arbitrary convention? Continuing to repeat the above like a
> mantra doesn't really explain anything.
>

Thank you for asking. You're the first to not just say "you're wrong."

You design and implement a class so that it works correctly (modulo
errors, of course). You make things private if uncontrolled changes to
them will violate your class's invariants, which would violate the
assumptions underlying your interface functions. So you prevent access
to those things in order to make sure that your code (the code you wrote
to implement the class) works correctly.

If someone derives from your class in a way that doesn't make sense that
doesn't affect your code. It still works right.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Mon, 9 Dec 2002 01:18:08 +0000 (UTC)
Raw View
Peter Dimov wrote:
>
> petebecker@acm.org (Pete Becker) wrote in message news:<3DF14A6E.4096445@acm.org>...
> > Randy Maddox wrote:
> > >
> > > I also firmly agree with James Kuyper and others who state that the
> > > designer of a class is in a position to know better whether or not
> > > his/her class should be derived from.
> >
> > Nobody has disputed this.
>
> For the record, I do dispute this claim. The designer knows whether
> the class has been designed for inheritance. The user knows whether,
> in a particular context, derivation from the class is necessary (or
> the best alternative) in order to accomplish the task at hand.
>

That's a somewhat different claim, and it's the one I've been making as
well. The designer of a class decides whether it should be derived from,
and that affects the design, the implementation, and the documentation.
What some people say they want is to be able to go a step further and
enforce that decision in user code.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Mon, 9 Dec 2002 01:18:17 +0000 (UTC)
Raw View
"James Kuyper Jr." wrote:
>
> Pete Becker wrote:
> > Randy Maddox wrote:
> >
> >>I also firmly agree with James Kuyper and others who state that the
> >>designer of a class is in a position to know better whether or not
> >>his/her class should be derived from.
> >
> >
> > Nobody has disputed this.
>
> Yes you have; you've asked:
>

You're right: on rereading his statement I see it's a broader than I
thought at first.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Mon, 9 Dec 2002 01:19:26 +0000 (UTC)
Raw View
Francis Glassborow wrote:
>
> In article <3DF27F8B.9F19651F@acm.org>, Pete Becker <petebecker@acm.org>
> writes
> >class Array
> >{      // sketch only, of course
> >public:
> >       void append(int value) { data[count++] = value; }
> >private:
> >       int *data;
> >       int count;
> >};
> >
> >Now, the reason you make 'count' private is that if it's public user
> >code can modify count in unpredictable ways, and then append will not do
> >what it is supposed to do.
>
> But any responsible programmer who has read the documentation would not
> do that.

The difference, for the umpteenth time, is in whose code you're
protecting. You use private to protect YOUR CODE, that is, the code you
wrote to implement YOUR CLASS. Unless you're the user's mother it's not
your responsibility to try to make him into a better programmer.

>
> I suspect that you would be defending  'final'  had it been in the
> original design of C++.

Another ad hominem argument. Please confine your comments to addressing
the merits of the subject under discussion.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Mon, 9 Dec 2002 01:19:58 +0000 (UTC)
Raw View
Niklas Matthies wrote:
>
> On 2002-12-05 19:43, Pete Becker <petebecker@acm.org> wrote:
> > Niklas Matthies wrote:
> >>
> >> On 2002-12-05 18:23, Pete Becker <petebecker@acm.org> wrote:
> >> > Scott Mayo wrote:
> >> [...]
> >> >> Give me 'final'. Give me anything that will let me have
> >> >> the *compiler* require that people follow the rules I
> >> >> set down when I designed my classes, especially if it
> >> >> also has a shot of improving optimizations.
> >> >
> >> > Why do you think you're better qualified to judge the code that someone
> >> > else is writing than they are?
> >>
> >> With regard to derivation, the question is who is better qualified to
> >> judge whether a class should or shouldn't be derived from: The author of
> >> said class, or the programmer who merely wants to use that class as a
> >> base for his own?
> >
> > The programmer who "merely" wants to derive from that class knows what
> > he wants to use it for. The author of the class does not.
>
> Right, and the latter is the reason why the author might want to
> disallow derivation.

I don't follow this. If the author doesn't know what the programmer
wants to use the class for, why should the author want to disallow
derivation?

>
> > The programmer is in a better position to know what he needs than the
> > author of the class. Writing a class shouldn't turn you into a nanny.
>
> Why not? It's your class, after all.
>

Yup, that's the bottom line, isn't it? Doesn't what users want; you
wrote it, you decide what others can do with it.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Mon, 9 Dec 2002 07:17:16 +0000 (UTC)
Raw View
Dave Harris wrote:
> We would like foo() to be dynamically dispatched in the first template
> instantiation, and statically in the second, without having to rewrite the
> template.

And since simple templates like this are inlined, and you have
a Base reference but a Derived object, that's exactly what will
happen!

 > Functions which are virtual in the base class cannot be made
 > non-virtual in the derived class, even though this is often desired.

But why is this desired? Obviously, making methods non-virtual in the
derived class only affects direct calls to objects of the derived class.
In that case, there is no reason not to use another name for the "final"
method.

---
[ 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: fonseca@mip.sdu.dk (=?ISO-8859-1?Q?Ren=E9_M=F8ller_Fonseca?=)
Date: Mon, 9 Dec 2002 09:37:49 +0000 (UTC)
Raw View
Some additional notes which I think passed you all by.

1. Inheritance may be blocked by making all constructors private. Of caus=
e you need a static method or a friend to construct instances of the clas=
s in question.

2. Singletons are candiates for blocked inheritance. However, if possible=
 the class should be hidden in a private header/source.

3. A "final" keyword is not required due to point 1 and the "inline" keyw=
ord (think about it).

4. Utilizing private attributes makes it more easy to guarantee backwards=
 compatibility. This is just one important example.

5. Newgroups can be more entertaining than a soap opera :)

6. This could be the end of the discussion. But will it be so. Tune in ne=
xt Tuesday for more?

cheers,
Ren=E9

Pete Becker wrote:
> Francis Glassborow wrote:
>=20
>>In article <3DF27F8B.9F19651F@acm.org>, Pete Becker <petebecker@acm.org=
>
>>writes
>>
>>>class Array
>>>{      // sketch only, of course
>>>public:
>>>      void append(int value) { data[count++] =3D value; }
>>>private:
>>>      int *data;
>>>      int count;
>>>};
>>>
>>>Now, the reason you make 'count' private is that if it's public user
>>>code can modify count in unpredictable ways, and then append will not =
do
>>>what it is supposed to do.
>>
>>But any responsible programmer who has read the documentation would not
>>do that.
>=20
>=20
> The difference, for the umpteenth time, is in whose code you're
> protecting. You use private to protect YOUR CODE, that is, the code you
> wrote to implement YOUR CLASS. Unless you're the user's mother it's not
> your responsibility to try to make him into a better programmer.
>=20
>=20
>>I suspect that you would be defending  'final'  had it been in the
>>original design of C++.
>=20
>=20
> Another ad hominem argument. Please confine your comments to addressing
> the merits of the subject under discussion.
>=20

---
[ 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: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: Mon, 9 Dec 2002 09:38:51 +0000 (UTC)
Raw View
petebecker@acm.org (Pete Becker) writes:

>"James Kuyper Jr." wrote:
>> Pete Becker wrote:
>> > Now, the reason you make 'count' private is that if it's public user
>> > code can modify count in unpredictable ways, and then append will not do
>> > what it is supposed to do.
>>
>> Which is needed only to make other people's code work. It doesn't make
>> your code work, because even if 'count' weren't private, you'd never do
>> something as stupid as changing 'count' from outside the append()
>> member.
>
>Okay, it's clear that your goal is to disagree, not to understand.
>There's no point in continuing this discussion.

Accusing an individual of bad motives ("your goal is to disagree")
is an ad hominem attack, which IMHO should not have been allowed by
the moderators.  I hope that you will retract it.

It seems clear to me that both "private" and "final" can be used
to enforce invariants.  "private" can be used to enforce the invariant
that a private data member has not been modified by code outside the
class.  "final" can be used to enforce the invariant that a pointer
points to a base class object, not a derived object.

Consider, for example, a swap() member:

 /* final */ class Array
 {     // sketch only, of course
 public:
       void swap(Array &x) {
          std::swap(data, x.data);
   std::swap(count, x.count);
       }
       void append(int value) { data[count++] = value; }
 private:
       int *data;
       int count;
 };

Here the correctness of `append' relies on the validity of the `count'
member, which is enforced by the use of "private".  Likewise, the correctness
of the `swap' member function relies on the validity of the `x' and `this'
parameters, which must each point to an object of class `Array', not a
derived class.  This could be enforced by the use of "final" on the
Array class.

As far as I can tell, the distinction that you are making between
"your code" and "other people's code" doesn't apply.  In both cases,
it is the code in the Array class itself that won't work, but only if
some other code is written which uses the Array class in the wrong way.

So I am trying to understand why you object to this proposed extension.
As shown above, both "final" and "private" can be used to enforce invariants
which member functions rely on as preconditions.  Is there some other
distinction between "final" and "private" which leads you to oppose "final"?

--
Fergus Henderson <fjh@cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.

---
[ 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: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: Mon, 9 Dec 2002 09:47:29 +0000 (UTC)
Raw View
petebecker@acm.org (Pete Becker) writes:

>Scott Mayo wrote:
>>
>> Realistically, a lot of us work with people for whom
>> English is a second language. English documentation and
>> even comments in the code don't always have much
>> authority in such a setting, even when the will to do the
>> right thing is present. But *everyone* understands
>> compiler error messages.
>
>If someone can't read the documentation then misusing inheritance is the
>least of your worries. How are they going to write any code that uses
>your class?

Treating it as a black-and-white issue, either they can read the documentation
or they can't, is a false dichotomy.  Those for whom English is a second
language will most likely be able to read and understand some of the
documention, but not all of it.

But even programmers who are fully fluent in English are not always be
able to read, understand, remember, and apply every relevant piece of
documentation.

Furthermore, no programmer can read documentation that has not yet been
written.  But "final" can still be useful in such cases.  For example,
suppose your program has an Array class, and you want to add a swap()
method to it, which won't work if passed a class derived from Array
(as in the example in my earlier post).  If the Array class is used in
a large number of places, it may be difficult to determine whether there
is any code which derives from Array.  However, it's easy to add "final"
to the class definition, and if you do that, you can be assured that the
compiler which catch any code which derives from Array.  So "final" can
be useful for code maintenance in a way that ordinary documentation can't.

Documentation which is concise, uses a standardized form, and is enforced
by the compiler is a lot more useful than documentation which is not.

--
Fergus Henderson <fjh@cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.

---
[ 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: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: Mon, 9 Dec 2002 18:11:40 +0000 (UTC)
Raw View
petebecker@acm.org (Pete Becker) writes:

>What concrete evidence is there that being able to prevent inheritance
>improves program quality?

What concrete evidence is there that *any* C++ feature improves
program quality?

Being able to prevent inheritence means that certain kinds of preconditions,
whose violation would lead to program bugs, can easily be statically enforced.
That's a fact.

Whether this would lead to improved program quality overall is a question
on which there is little or no concrete evidence.  I certainly believe
that it would.  But obtaining accurate and reliable empirical evidence on
these sort of matters is not feasible, due to the cost of undertaking
empirical studies in programming language design, to the difficulty
of controlling the experiment so that only a single factor is tested,
and to determining whether the results of such experiments would carry
over to results in an uncontrolled environment.

Why should the bar be set higher for this feature than for other C++ features?

--
Fergus Henderson <fjh@cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.

---
[ 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: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: Mon, 9 Dec 2002 18:12:38 +0000 (UTC)
Raw View
francis.glassborow@ntlworld.com (Francis Glassborow) writes:

>I also note that proponents have suggested that 'final' should be
>overridable but only by deliberate action. I think that is a sane
>compromise.

With the exception of redefining virtual methods, it's possible to
achieve essentially the same effects as class derivation by using
composition, delegation, and on making certain implicit conversions
explicit.

(That is, make the class you want to derive from a member
rather than a base class; explicitly forward the appropriate
member functions to the base class; and refer to the member
any time that an implicit derived-to-base conversion would have
been invoked.)

As for the possibility of overriding virtual functions on a class declared
"final", well, I think there would be very few benefits in allowing this,
and that they would be far outweighed by the drawbacks (e.g. making programs
more difficult to reason about).  So I do *not* think it would be a good
idea to provide a language extension for this.  Like "private", "final"
would be best if there was no language-sanctioned way to override it.

--
Fergus Henderson <fjh@cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.

---
[ 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: kuyper@wizard.net ("James Kuyper Jr.")
Date: Mon, 9 Dec 2002 18:12:52 +0000 (UTC)
Raw View
Pete Becker wrote:
> "James Kuyper Jr." wrote:
....
>>In any event, to the extent that the
>>distinction is clear, private/protected very clearly comes down on the
>>other side of fence; just like 'final', it's NEVER needed to make your
>>own code work.
>>
>
>
> When you write a class you define its interface, and you specify a set
> of class invariants. The interface always preserves the class
> invariants. If allowing access to a piece of member data permits
> breaking the class invariants then you make it private. Otherwise you
> leave open the possibility that uses will do something that prevents
> your code from working right.

By your own arguments, documenting what shouldn't be done should be
sufficient. That argument applies equally well (or more accurately,
"equally poorly") to final, private/protected, and const. In all three
cases, the feature prevents people from having the option of doing
something that could make your code break when they use it. In all three
cases, the feature would never be needed if the applicable restrictions
were correctly documented, and if that documentation was read,
understood, and infallibly obeyed.

---
[ 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: kuyper@wizard.net ("James Kuyper Jr.")
Date: Mon, 9 Dec 2002 18:13:04 +0000 (UTC)
Raw View
Pete Becker wrote:
....
> It is, indeed, one of the roles of a government to provide rules for the
> safety of its citizens. Writing a class doesn't make a programmer into a
> government.

A better analogy is that being the owner of something allows one to set
restrictions on how that thing is used. Writing a class does make you
the owner of it, unless you've made other arrangements (i.e. working for
someone else, who becomes the actual owner, or publishing your code for
free public use and modification).

---
[ 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: rmaddox@isicns.com (Randy Maddox)
Date: Mon, 9 Dec 2002 18:13:37 +0000 (UTC)
Raw View
petebecker@acm.org (Pete Becker) wrote in message news:<3DF3EB63.84638038@acm.org>...
> Peter Dimov wrote:
> >
> > petebecker@acm.org (Pete Becker) wrote in message news:<3DF14A6E.4096445@acm.org>...
> > > Randy Maddox wrote:
> > > >
> > > > I also firmly agree with James Kuyper and others who state that the
> > > > designer of a class is in a position to know better whether or not
> > > > his/her class should be derived from.
> > >
> > > Nobody has disputed this.
> >
> > For the record, I do dispute this claim. The designer knows whether
> > the class has been designed for inheritance. The user knows whether,
> > in a particular context, derivation from the class is necessary (or
> > the best alternative) in order to accomplish the task at hand.
> >
>
> That's a somewhat different claim, and it's the one I've been making as
> well. The designer of a class decides whether it should be derived from,
> and that affects the design, the implementation, and the documentation.
> What some people say they want is to be able to go a step further and
> enforce that decision in user code.
>
> --
> Pete Becker
> Dinkumware, Ltd. (http://www.dinkumware.com)
>
> ---

Exactly so.  The designer of the class knows what assumptions they are
making, and if one of those assumptions is that the class will not be
derived from then that will impact the class design.  That is, a class
that is intended to be used as a base class is explicitly designed
differently, using different assumptions, than a class that is
designed as a base class.  Not every class is intended, designed, or
even necessarily safe to be used as a base class.

No one has argued against that last statement, at least not as far as
I can tell, and yet several have argued very strongly that compiler
support for the concept of a class not intended to be derived from is
somehow very wrong.  I am at a loss to grasp the counter argument.  If
some classes really are best designed as leaf classes with no further
inheritance, then why is compiler support for this a bad thing?

The corresponding argument with regard to const is not being made.  If
a class designer knows that some member of the class should only be
initialized at certain points and not be changed later, then they
express this intent by declaring the member as const, and the compiler
then prevents them, or others, from mistakenly violating that intent,
thus ensuring that the corresponding assumption remains valid.  This
is (almost) universally accepted as a good thing.

How is the proposal for final really different?  It would allow the
compiler to support a statment of intent by the class designer, which
would in turn allow that designer to have stronger faith that intent
will not be accidentally violated.  The provision of some means to
explicitly override final, as has been suggested, would even allow
that intent to be deliberatly violated if and as appropriate, much as
constness can be cast away in some rare cases.

I believe that the proposal for final as presented in this thread is a
good one that meets a real need.  The counter argument of merely
declaring that anyone who thinks this way is arrogantly trampling the
rights of users of their class to derive from it willy-nilly is
nothing more than an ad hominem attack that makes no attempt to
address the issue.  If this were difficult to implement, or would
break existing code, or had no clear benefit then those would be valid
arguments.  However, I do not see those points being made.

Randy.

---
[ 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: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Mon, 9 Dec 2002 18:22:30 +0000 (UTC)
Raw View
In article <3DF3EF1D.D313EEE3@acm.org>, Pete Becker <petebecker@acm.org>
writes
>
>The difference, for the umpteenth time, is in whose code you're
>protecting. You use private to protect YOUR CODE, that is, the code you
>wrote to implement YOUR CLASS. Unless you're the user's mother it's not
>your responsibility to try to make him into a better programmer.

And I think that Fergus has clearly demonstrated that that is a false
distinction. swap() is only one example of a function that sometimes
relies on an invariant.

For me, that example is particularly persuasive because it illustrates a
legitimate requirement for my code to work correctly that can be
invalidated by deriving from my code.

>
>>
>> I suspect that you would be defending  'final'  had it been in the
>> original design of C++.
>
>Another ad hominem argument. Please confine your comments to addressing
>the merits of the subject under discussion.

It was not an argument, just a comment.


--
Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ 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: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: Mon, 9 Dec 2002 18:28:10 +0000 (UTC)
Raw View
petebecker@acm.org (Pete Becker) writes:

>Unless you're the user's mother it's not
>your responsibility to try to make him into a better programmer.

It is every class designer's responsibility to do their best
to ensure that the classes that they design are easy to use,
and hard to misuse.

Doing this won't make the users of the class better programmers,
but it may well make them produce better programs.

--
Fergus Henderson <fjh@cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.

---
[ 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: allan_w@my-dejanews.com (Allan W)
Date: Thu, 5 Dec 2002 22:12:38 +0000 (UTC)
Raw View
petebecker@acm.org (Pete Becker) wrote
> Niklas Matthies wrote:
> > So why not do the same with other features like 'const' or 'private',
> > just documenting it instead of declaring it within the language?
> >
>
> The difference is between "my code won't work right if you do this" and
> "your code won't work right if you do this." The former is your
> responsibility. The latter is not.

Which is which?

When I write a class that has const members, am I saying "my code won't
work right if you change this" or "your code won't work right if you
change this?" Which one does it mean when I make a member private?
How about documenting the fact that a class shouldn't be derived from?
Why is this different? Why would asking the compiler to enforce that
requirement be harmful?

---
[ 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: kuyper@wizard.net ("James Kuyper Jr.")
Date: Thu, 5 Dec 2002 23:45:41 +0000 (UTC)
Raw View
Pete Becker wrote:
> Scott Mayo wrote:
>
>>"Pete Becker" <petebecker@acm.org> wrote in message
>>news:3DEEA51B.EA2D1066@acm.org...
....
>>Give me 'final'. Give me anything that will let me have
>>the *compiler* require that people follow the rules I
>>set down when I designed my classes, especially if it
>>also has a shot of improving optimizations.
>>
>
>
> Why do you think you're better qualified to judge the code that someone
> else is writing than they are?

The other user's code is affected by such language features, only if
they're trying to connect their code with mine. And I will, with all due
modesty, assert that the designer of a module DOES generally know more
about the correct use of that module than the end user; even if that use
occurs in someone else's code. This isn't always true, but it's true
often enough to justify this type of feature.

I'm not necessarily arguing for this particular feature: I think that
use of "final" generally represents a failure of imagination. However,
in general, features like 'private' and 'protected' and 'const' do serve
a useful purpose, even when they interfere with other people's code. In
fact, they serve a useful purpose BECAUSE they interfere with other
people's code.

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Thu, 5 Dec 2002 23:46:34 +0000 (UTC)
Raw View
"James Kuyper Jr." wrote:
>
> Pete Becker wrote:
> > "James Kuyper Jr." wrote:
> ....
> >>Fixing the real problem is a great idea, and reasonable efforts should
> >>be made in that direction. That doesn't make it any less useful to also
> >>trigger alerts when the symptom comes up.
> >
> >
> > It encourages hacking, under the false belief that the compiler will
> > catch mistakes.
>
> That belief isn't false; the compiler will catch mistakes - sometimes.
> The false belief is that it will catch all mistakes; you're not going to
> eliminate that belief by increasing the number of mistakes it doesn't
> catch.

The more mistakes the compiler catches the more people will rely on it
instead thinking about what they're doing.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Thu, 5 Dec 2002 23:46:43 +0000 (UTC)
Raw View
Ken Alverson wrote:
>
> "Pete Becker" <petebecker@acm.org> wrote in message
> news:3DEF561E.8938CBDA@acm.org...
> > "James Kuyper Jr." wrote:
> > >
> > > Fixing the real problem is a great idea, and reasonable efforts
> should
> > > be made in that direction. That doesn't make it any less useful to
> also
> > > trigger alerts when the symptom comes up.
> >
> > It encourages hacking, under the false belief that the compiler will
> > catch mistakes.
>
> No more than an airbag encourages wrecking your car, under the false
> belief that the airbag will save your life.
>

If you truly believe that programmers need not be any better at their
profession than drivers are at driving then this has some merit. Of
course, that makes "profession" a rather empty word.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Thu, 5 Dec 2002 23:48:08 +0000 (UTC)
Raw View
Scott Mayo wrote:
>
> Realistically, a lot of us work with people for whom
> English is a second language. English documentation and
> even comments in the code don't always have much
> authority in such a setting, even when the will to do the
> right thing is present. But *everyone* understands
> compiler error messages.
>

If someone can't read the documentation then misusing inheritance is the
least of your worries. How are they going to write any code that uses
your class?

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kuyper@wizard.net ("James Kuyper Jr.")
Date: Thu, 5 Dec 2002 23:48:11 +0000 (UTC)
Raw View
Pete Becker wrote:
....
> The programmer who "merely" wants to derive from that class knows what
> he wants to use it for. The author of the class does not. The programmer
> is in a better position to know what he needs than the author of the
> class. Writing a class shouldn't turn you into a nanny.

If there is some feature of a class that makes it inappropriate to
derive from it, the author of the class will know that better than the user.


---
[ 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: petebecker@acm.org (Pete Becker)
Date: Thu, 5 Dec 2002 23:59:14 +0000 (UTC)
Raw View
"James Kuyper Jr." wrote:
>
> Pete Becker wrote:
> ....
> > The programmer who "merely" wants to derive from that class knows what
> > he wants to use it for. The author of the class does not. The programmer
> > is in a better position to know what he needs than the author of the
> > class. Writing a class shouldn't turn you into a nanny.
>
> If there is some feature of a class that makes it inappropriate to
> derive from it, the author of the class will know that better than the user.
>

Yup. Which is why you document the feature that makes it inappropriate,
and let users judge for themselves whether it's appropriate for their
needs.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kuyper@wizard.net ("James Kuyper Jr.")
Date: Fri, 6 Dec 2002 00:23:20 +0000 (UTC)
Raw View
Pete Becker wrote:
> "James Kuyper Jr." wrote:
....
>>That belief isn't false; the compiler will catch mistakes - sometimes.
>>The false belief is that it will catch all mistakes; you're not going to
>>eliminate that belief by increasing the number of mistakes it doesn't
>>catch.
>
>
> The more mistakes the compiler catches the more people will rely on it
> instead thinking about what they're doing.

No - the ones dumb enough to rely on the compiler INSTEAD of thinking
will continue do so, no matter how unreliable it is. If it's
sufficiently unreliable at catching their mistakes, they won't use it at
all, because they won't be able to get any useful results out of it. The
smart ones will rely on the compiler to catch their errors IN ADDITION
to thinking about what they're doing, and will rely on it more as it
gets more reliable at catching them.

---
[ 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: kuyper@wizard.net ("James Kuyper Jr.")
Date: Fri, 6 Dec 2002 00:35:44 +0000 (UTC)
Raw View
===================================== MODERATOR'S COMMENT:
 C++-Standard-related content flatlining...


===================================== END OF MODERATOR'S COMMENT
Pete Becker wrote:
> Ken Alverson wrote:
>
>>"Pete Becker" <petebecker@acm.org> wrote in message
>>news:3DEF561E.8938CBDA@acm.org...
>>
>>>"James Kuyper Jr." wrote:
....
>>>It encourages hacking, under the false belief that the compiler will
>>>catch mistakes.
>>
>>No more than an airbag encourages wrecking your car, under the false
>>belief that the airbag will save your life.
>>
>
>
> If you truly believe that programmers need not be any better at their
> profession than drivers are at driving then this has some merit. Of
> course, that makes "profession" a rather empty word.

Programming is a job, not an art form. The world needs lots of
programmers. You can't fill a demand that high without bringing in
people who aren't committed to the highest possible standards of
professionalism. The job still needs to get done, even if it must be
done by those people. And those people do indeed need the software
equivalent of airbags.

---
[ 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: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Fri, 6 Dec 2002 00:35:52 +0000 (UTC)
Raw View
In article <3DEFAC58.E3FED5DD@acm.org>, Pete Becker <petebecker@acm.org>
writes
>If it probably won't work right then there are cases in which it will
>work right. Why do you want to prevent users of your class from using it
>in those cases?

Perhaps because in the modern litigious age I want to be able to
demonstrate that I took every reasonable precaution to prevent users
having accidents when they elect to (ab)use my code.

I would like to have a choice. I do not have to use final if I do not
want to, but at the moment I do not have the option.


--
Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Fri, 6 Dec 2002 00:59:13 +0000 (UTC)
Raw View
"James Kuyper Jr." wrote:
>
> ===================================== MODERATOR'S COMMENT:
>  C++-Standard-related content flatlining...
>
> ===================================== END OF MODERATOR'S COMMENT
> Pete Becker wrote:
> > Ken Alverson wrote:
> >
> >>"Pete Becker" <petebecker@acm.org> wrote in message
> >>news:3DEF561E.8938CBDA@acm.org...
> >>
> >>>"James Kuyper Jr." wrote:
> ....
> >>>It encourages hacking, under the false belief that the compiler will
> >>>catch mistakes.
> >>
> >>No more than an airbag encourages wrecking your car, under the false
> >>belief that the airbag will save your life.
> >>
> >
> >
> > If you truly believe that programmers need not be any better at their
> > profession than drivers are at driving then this has some merit. Of
> > course, that makes "profession" a rather empty word.
>
> Programming is a job, not an art form. The world needs lots of
> programmers. You can't fill a demand that high without bringing in
> people who aren't committed to the highest possible standards of
> professionalism. The job still needs to get done, even if it must be
> done by those people. And those people do indeed need the software
> equivalent of airbags.
>

What concrete evidence is there that being able to prevent inheritance
improves program quality?

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Fri, 6 Dec 2002 01:46:51 +0000 (UTC)
Raw View
Allan W wrote:
>
> petebecker@acm.org (Pete Becker) wrote
> > Niklas Matthies wrote:
> > > So why not do the same with other features like 'const' or 'private',
> > > just documenting it instead of declaring it within the language?
> > >
> >
> > The difference is between "my code won't work right if you do this" and
> > "your code won't work right if you do this." The former is your
> > responsibility. The latter is not.
>
> Which is which?
>
> When I write a class that has const members, am I saying "my code won't
> work right if you change this" or "your code won't work right if you
> change this?"

I don't know. Why did you make it const? I'd make it const if that was
necessary for the correct behavior of my class.

>  Which one does it mean when I make a member private?

I don't know. Why did you make it private? I'd make it private if that
was necessary for the correct behavior of my class.

> How about documenting the fact that a class shouldn't be derived from?

Why shouldn't it be derived from?

> Why is this different? Why would asking the compiler to enforce that
> requirement be harmful?
>

I guess I'm just not presumptious enough to believe that I'm the best
judge of how other programmers should solve problems I've never seen.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Fri, 6 Dec 2002 01:47:18 +0000 (UTC)
Raw View
"James Kuyper Jr." wrote:
>
> I'm not necessarily arguing for this particular feature: I think that
> use of "final" generally represents a failure of imagination. However,
> in general, features like 'private' and 'protected' and 'const' do serve
> a useful purpose, even when they interfere with other people's code. In
> fact, they serve a useful purpose BECAUSE they interfere with other
> people's code.
>

Yup. I haven't disputed features like 'private' and 'protected' and
'const'.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kuyper@wizard.net ("James Kuyper Jr.")
Date: Fri, 6 Dec 2002 01:47:39 +0000 (UTC)
Raw View
Pete Becker wrote:
> Scott Mayo wrote:
>
>>Realistically, a lot of us work with people for whom
>>English is a second language. English documentation and
>>even comments in the code don't always have much
>>authority in such a setting, even when the will to do the
>>right thing is present. But *everyone* understands
>>compiler error messages.
>>
>
>
> If someone can't read the documentation then misusing inheritance is the
> least of your worries. How are they going to write any code that uses
> your class?

"can't read" and "have difficulty reading" are two different things. I
can assure you from personal experience that it is possible (but very
difficult) to get useful work out of a team who aren't all fluent in the
project's official language. In such an environment, compiler messages
are at least as effective as documentation for conveying requirements.

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Fri, 6 Dec 2002 01:48:05 +0000 (UTC)
Raw View
"James Kuyper Jr." wrote:
>
> Pete Becker wrote:
> > "James Kuyper Jr." wrote:
> ....
> >>That belief isn't false; the compiler will catch mistakes - sometimes.
> >>The false belief is that it will catch all mistakes; you're not going to
> >>eliminate that belief by increasing the number of mistakes it doesn't
> >>catch.
> >
> >
> > The more mistakes the compiler catches the more people will rely on it
> > instead thinking about what they're doing.
>
> No - the ones dumb enough to rely on the compiler INSTEAD of thinking
> will continue do so, no matter how unreliable it is.

Undoubtedly. But I don't think it's important to write code that is safe
for incompetent programmers.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Fri, 6 Dec 2002 01:48:24 +0000 (UTC)
Raw View
Francis Glassborow wrote:
>
> In article <3DEFAC58.E3FED5DD@acm.org>, Pete Becker <petebecker@acm.org>
> writes
> >If it probably won't work right then there are cases in which it will
> >work right. Why do you want to prevent users of your class from using it
> >in those cases?
>
> Perhaps because in the modern litigious age I want to be able to
> demonstrate that I took every reasonable precaution to prevent users
> having accidents when they elect to (ab)use my code.
>

Is this based on advice from a competent lawyer?

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: scottm@toast.net (Scott Mayo)
Date: Fri, 6 Dec 2002 06:19:39 +0000 (UTC)
Raw View
"Pete Becker" <petebecker@acm.org> wrote in message
news:3DEFBCE7.A80AFBA9@acm.org...
> Scott Mayo wrote:

> > Realistically, a lot of us work with people for whom
> > English is a second language. English documentation and
> > even comments in the code don't always have much
> > authority in such a setting, even when the will to do the
> > right thing is present. But *everyone* understands
> > compiler error messages.


> If someone can't read the documentation then misusing inheritance is the
> least of your worries. How are they going to write any code that uses
> your class?

I'm not talking about functional illiterates. I'm talking about
people who struggle with English and struggle a little with
C++, but nonetheless are called upon to do significant
programming work in predominately English environments.
I'm talking about the kind of person who might not understand
why it's bad to return pointers to automatic variables, and
don't quite believe you when you tell them that a bald ++i,
for an extern int i, in a function called by multiple threads at once,
isn't quite as safe as it looks. Trust me, they exist, and they are
usually found in the numberless ranks of  "junior programmers".
And they implement the bulk of the software that takes your
online orders, handles insurance billing, and operates the "remove
me from your mailing list" function in most bulk emailers.

If you aren't worried yet, I don't know why. As far as I can make
out, compiler warnings are the last defence of western civilization,
and more checking is better than less.

Some classes are written in a fashion that makes them unsafe
to extend. Some are PODs and they know they are PODs and
they make assumptions about internal layout, for example, that fwrite
and fread makes a suitable save() and restore() mechanism for the
data. This is common in ports from C. Are such assumptions valid
C++? I think the standard explicitly blesses this usage. But freely
extensible? Not a good idea - someone will naively extend save()/restore(),
and end up fread()ing over Something That Man Was Not Meant
To Fread(), like a sneaky hidden virtual function table.

PODs are great candidates for 'final'.



---
[ 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: comp.std.c++_2002-12-06@nmhq.net (Niklas Matthies)
Date: Fri, 6 Dec 2002 16:32:17 +0000 (UTC)
Raw View
On 2002-12-05 19:43, Pete Becker <petebecker@acm.org> wrote:
> Niklas Matthies wrote:
>>
>> On 2002-12-05 18:23, Pete Becker <petebecker@acm.org> wrote:
>> > Scott Mayo wrote:
>> [...]
>> >> Give me 'final'. Give me anything that will let me have
>> >> the *compiler* require that people follow the rules I
>> >> set down when I designed my classes, especially if it
>> >> also has a shot of improving optimizations.
>> >
>> > Why do you think you're better qualified to judge the code that someone
>> > else is writing than they are?
>>
>> With regard to derivation, the question is who is better qualified to
>> judge whether a class should or shouldn't be derived from: The author of
>> said class, or the programmer who merely wants to use that class as a
>> base for his own?
>
> The programmer who "merely" wants to derive from that class knows what
> he wants to use it for. The author of the class does not.

Right, and the latter is the reason why the author might want to
disallow derivation.

> The programmer is in a better position to know what he needs than the
> author of the class. Writing a class shouldn't turn you into a nanny.

Why not? It's your class, after all.

-- Niklas Matthies

---
[ 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: thomas.hyer@ubsw.com (Tom Hyer)
Date: Fri, 6 Dec 2002 17:14:23 +0000 (UTC)
Raw View
petebecker@acm.org (Pete Becker) wrote in message >
> Yup. Which is why you document the feature that makes it inappropriate,
> and let users judge for themselves whether it's appropriate for their
> needs.
>

    But in this discussion, you still have not said anything about
'final' in particular; that is, your only argument could just as well
be applied to 'private'/'protected', and almost to 'const'.  Thus you
are not making a case against final, but waging a campaign against any
restrictive statements of intent.

    Also, your argument presupposes a particular and rather rigid
development process.  A 'final' keyword would be a valuable aid to
incremental or experimental development, where it would be attached to
classes under development, postponing (sometimes forever) the need to
make them more generic and removing the labor of documenting that part
of their status.

    And before you start:  yes, for those of us whose software deals
with the intractable outside world, there is such a thing as
"experimental" or experiment-driven development.

-- Tom Hyer

---
[ 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: thomas.hyer@ubsw.com (Tom Hyer)
Date: Fri, 6 Dec 2002 17:14:28 +0000 (UTC)
Raw View
petebecker@acm.org (Pete Becker) wrote in message news:<3DED8110.6FF05730@acm.org>...
>
> The distinction to keep in mind is that between "if you do this my code
> won't work" and "if you do this your code won't work." The former is why
> you make things private. The latter is not your responsibility.
>
    But the former is never a reason to make something private.
Making everything public, and documenting the changes which break
class invariants, should be just as effective, no?

-- Tom Hyer

---
[ 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: kuyper@wizard.net ("James Kuyper Jr.")
Date: Fri, 6 Dec 2002 17:14:50 +0000 (UTC)
Raw View
Pete Becker wrote:
> Allan W wrote:
>
>>petebecker@acm.org (Pete Becker) wrote
>>
>>>Niklas Matthies wrote:
>>>
>>>>So why not do the same with other features like 'const' or 'private',
>>>>just documenting it instead of declaring it within the language?
>>>>
>>>
>>>The difference is between "my code won't work right if you do this" and
>>>"your code won't work right if you do this." The former is your
>>>responsibility. The latter is not.
>>
>>Which is which?
....
>> Which one does it mean when I make a member private?
>
>
> I don't know. Why did you make it private? I'd make it private if that
> was necessary for the correct behavior of my class.

How could it be necessary for the correct behavior of your class? Code
that never attempts anything inappropriate with the class won't work any
differently with 'private' than it would have if that member were
'public'. It's not for causing correct behavior, but for preventing
incorrect behavior. The incorrect behavior it prevents can't even occur
as part of the class definition, since inside that definition there's no
difference between 'public' and 'private'.

....
>>Why is this different? Why would asking the compiler to enforce that
>>requirement be harmful?
>>
>
>
> I guess I'm just not presumptious enough to believe that I'm the best
> judge of how other programmers should solve problems I've never seen.

Except, of course, when you designate certain members of your classes
private. By doing that, you're preventing those other programmers from
solving problems you've never seen, by accessing those members. You feel
presumptuous enough to make that decision for them, why not this other
decision as well? I'm afraid I don't see the distinction.

---
[ 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: rmaddox@isicns.com (Randy Maddox)
Date: Fri, 6 Dec 2002 17:15:13 +0000 (UTC)
Raw View
petebecker@acm.org (Pete Becker) wrote in message news:<3DEFAD14.2DD48001@acm.org>...
> "James Kuyper Jr." wrote:
> >
> > Pete Becker wrote:
> > > "James Kuyper Jr." wrote:
>  ....
> > >>Fixing the real problem is a great idea, and reasonable efforts should
> > >>be made in that direction. That doesn't make it any less useful to also
> > >>trigger alerts when the symptom comes up.
> > >
> > >
> > > It encourages hacking, under the false belief that the compiler will
> > > catch mistakes.
> >
> > That belief isn't false; the compiler will catch mistakes - sometimes.
> > The false belief is that it will catch all mistakes; you're not going to
> > eliminate that belief by increasing the number of mistakes it doesn't
> > catch.
>
> The more mistakes the compiler catches the more people will rely on it
> instead thinking about what they're doing.

Or, the more mistakes the compiler catches the fewer mistakes will be
left to find by debugging and testing.  Isn't that rather the whole
point of having a type system?  I say, if the compiler can catch a
mistake that is certainly a lot faster and cheaper than having to find
the problem later.

I also firmly agree with James Kuyper and others who state that the
designer of a class is in a position to know better whether or not
his/her class should be derived from.  Designing a class to be used as
a base class involves different assumptions than designing a leaf
class, and using a class under a different set of assumptions than
those under which it was designed can easily lead to unexpected
problems if the class design assumptions are violated.

Documentation is good, don't get me wrong, but it is a weak reed
compared to a compilation error.

Randy.

>
> --
> Pete Becker
> Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kuyper@wizard.net ("James Kuyper Jr.")
Date: Fri, 6 Dec 2002 17:15:23 +0000 (UTC)
Raw View
Pete Becker wrote:
....
> Undoubtedly. But I don't think it's important to write code that is safe
> for incompetent programmers.

Why not? They're not exactly an endangered species.

Note: in this context, to justify your objections, "incompetent
programmers" would have to include anyone who's ever had a problem
figuring out all of the intertwining implications of all the applicable
documentation when writing a single line of code, even if that single
line of code uses two dozen different classes from five different
libraries that were not written to work together.

However, even if your standards of competence are much more lenient than
that, there's still an awfully large number of incompetent programmers
out there.

---
[ 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: comp.std.c++_2002-12-06@nmhq.net (Niklas Matthies)
Date: Fri, 6 Dec 2002 17:15:53 +0000 (UTC)
Raw View
On 2002-12-05 19:51, Pete Becker <petebecker@acm.org> wrote:
> Niklas Matthies wrote:
>> On 2002-12-05 07:07, Pete Becker <petebecker@acm.org> wrote:
[...]
>> > The difference is between "my code won't work right if you do this" and
>> > "your code won't work right if you do this." The former is your
>> > responsibility. The latter is not.
>>
>> If "your code" is client code of "my code", then the former implies the
>> latter.
>
> No, it doesn't.

Yes, it does. :)

>> Currently, instead of using 'final', we have to say in the docs
>> "if you use my code in the context of a derived class, it probably won't
>> work right, so don't do this".
>
> If it probably won't work right then there are cases in which it will
> work right. Why do you want to prevent users of your class from using it
> in those cases?

I don't. I'm perfectly in favor of a facility that would allow to cast
"finalness" away. I just don't think that a class not intended and not
designed for derivation should be derivable from as a default.

-- Niklas Matthies

---
[ 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: comp.std.c++_2002-12-06@nmhq.net (Niklas Matthies)
Date: Fri, 6 Dec 2002 17:15:56 +0000 (UTC)
Raw View
On 2002-12-06 01:46, Pete Becker <petebecker@acm.org> wrote:
> Allan W wrote:
>> petebecker@acm.org (Pete Becker) wrote
>> > Niklas Matthies wrote:
>> > > So why not do the same with other features like 'const' or 'private',
>> > > just documenting it instead of declaring it within the language?
>> > >
>> >
>> > The difference is between "my code won't work right if you do this" and
>> > "your code won't work right if you do this." The former is your
>> > responsibility. The latter is not.
>>
>> Which is which?
>>
>> When I write a class that has const members, am I saying "my code won't
>> work right if you change this" or "your code won't work right if you
>> change this?"
>
> I don't know. Why did you make it const? I'd make it const if that was
> necessary for the correct behavior of my class.
>
>>  Which one does it mean when I make a member private?
>
> I don't know. Why did you make it private? I'd make it private if that
> was necessary for the correct behavior of my class.

It is never strictly necessary to make something a member const or
private for the correct behavior of the class. It is merely necessary
that client code doesn't do certain things with those members. You could
as well specify this in the class' documentation if you expect users of
the class to diligently read and adhere to this documentation, as you
apparently do with regard to derivation.

-- Niklas Matthies

---
[ 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: brangdon@cix.co.uk (Dave Harris)
Date: Fri, 6 Dec 2002 21:56:59 +0000 (UTC)
Raw View
hyrosen@mail.com (Hyman Rosen) wrote (abridged):
> struct Base
> {
>      virtual void foo();
> };
> struct Derived : Base
> {
>      void foo();
>      void final_foo() { this->Derived::foo(); }
> };

But renaming the function gives up (compile-time) polymorphism. For
example:

    template <typename T>
    void demo( T &t ) {
        t.foo();
    }

    void test() {
        Derived d;
        Base &b = d;
        demo( b );
        demo( d );
    }

We would like foo() to be dynamically dispatched in the first template
instantiation, and statically in the second, without having to rewrite the
template.


> Remember that C++, unlike Java, has non-virtual methods, and so
> doesn't really need a keyword which says to cut off virtuality.

This is one area where I think Java gets it right. In C++, functions which
are non-virtual in the base class can be made virtual in derived classes.
This is rarely what you want. Functions which are virtual in the base
class cannot be made non-virtual in the derived class, even though this is
often desired.

That said, a big difference between Java and C++ is that the former has a
security model which strives to protect against malice. C++ only tries to
protect against accident. "final" is an essential part of Java's security
model, but would not be so important for C++.

  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Sat, 7 Dec 2002 10:00:36 +0000 (UTC)
Raw View
Tom Hyer wrote:
>
> petebecker@acm.org (Pete Becker) wrote in message >
> > Yup. Which is why you document the feature that makes it inappropriate,
> > and let users judge for themselves whether it's appropriate for their
> > needs.
> >
>
>     But in this discussion, you still have not said anything about
> 'final' in particular; that is, your only argument could just as well
> be applied to 'private'/'protected', and almost to 'const'.  Thus you
> are not making a case against final, but waging a campaign against any
> restrictive statements of intent.

I've said three times now that it does not apply to private/protected
and why.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Sat, 7 Dec 2002 10:01:19 +0000 (UTC)
Raw View
Scott Mayo wrote:
>
> "Pete Becker" <petebecker@acm.org> wrote in message
> news:3DEFBCE7.A80AFBA9@acm.org...
> > Scott Mayo wrote:
>
> > > Realistically, a lot of us work with people for whom
> > > English is a second language. English documentation and
> > > even comments in the code don't always have much
> > > authority in such a setting, even when the will to do the
> > > right thing is present. But *everyone* understands
> > > compiler error messages.
>
> > If someone can't read the documentation then misusing inheritance is the
> > least of your worries. How are they going to write any code that uses
> > your class?
>
> I'm not talking about functional illiterates. I'm talking about
> people who struggle with English and struggle a little with
> C++, but nonetheless are called upon to do significant
> programming work in predominately English environments.
> I'm talking about the kind of person who might not understand
> why it's bad to return pointers to automatic variables, and
> don't quite believe you when you tell them that a bald ++i,
> for an extern int i, in a function called by multiple threads at once,
> isn't quite as safe as it looks. Trust me, they exist, and they are
> usually found in the numberless ranks of  "junior programmers".
> And they implement the bulk of the software that takes your
> online orders, handles insurance billing, and operates the "remove
> me from your mailing list" function in most bulk emailers.

Trust me, I know they exist. But please don't lump website designers
with C++ programmers. You do both a disservice.

>
> If you aren't worried yet, I don't know why.

Perhaps I have more respect for other progammers than you do.

> As far as I can make
> out, compiler warnings are the last defence of western civilization,
> and more checking is better than less.

Ignoring the hyperbole, warnings are often distractions. Our standard C
and C++ libraries compile with a wide range of compilers. Our customers
run our headers and our source code through all of those compilers, and
some of them like to crank up the warning level. As a result, I spend
far too much of my time rewriting correct code to conform to compiler
writers' notions of how code should be written. And then new versions of
the compilers come along and I have to do it all over again, because
they now apply different coding standards.

>
> Some classes are written in a fashion that makes them unsafe
> to extend. Some are PODs and they know they are PODs and
> they make assumptions about internal layout, for example, that fwrite
> and fread makes a suitable save() and restore() mechanism for the
> data. This is common in ports from C. Are such assumptions valid
> C++? I think the standard explicitly blesses this usage. But freely
> extensible? Not a good idea - someone will naively extend save()/restore(),
> and end up fread()ing over Something That Man Was Not Meant
> To Fread(), like a sneaky hidden virtual function table.

I take it you don't ever cross the street, because, after all, some
drunk driver might come screeching around the corner and run you down.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Sat, 7 Dec 2002 10:01:30 +0000 (UTC)
Raw View
Niklas Matthies wrote:
>
> On 2002-12-06 01:46, Pete Becker <petebecker@acm.org> wrote:
> > Allan W wrote:
> >> petebecker@acm.org (Pete Becker) wrote
> >> > Niklas Matthies wrote:
> >> > > So why not do the same with other features like 'const' or 'private',
> >> > > just documenting it instead of declaring it within the language?
> >> > >
> >> >
> >> > The difference is between "my code won't work right if you do this" and
> >> > "your code won't work right if you do this." The former is your
> >> > responsibility. The latter is not.
> >>
> >> Which is which?
> >>
> >> When I write a class that has const members, am I saying "my code won't
> >> work right if you change this" or "your code won't work right if you
> >> change this?"
> >
> > I don't know. Why did you make it const? I'd make it const if that was
> > necessary for the correct behavior of my class.
> >
> >>  Which one does it mean when I make a member private?
> >
> > I don't know. Why did you make it private? I'd make it private if that
> > was necessary for the correct behavior of my class.
>
> It is never strictly necessary to make something a member const or
> private for the correct behavior of the class. It is merely necessary
> that client code doesn't do certain things with those members. You could
> as well specify this in the class' documentation if you expect users of
> the class to diligently read and adhere to this documentation, as you
> apparently do with regard to derivation.
>

Once again: the difference is between "my code won't work right if you
do this" and "your code won't work right if you do this." You use
private to enforce the first of these. The second is not your
responsibility.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Sat, 7 Dec 2002 10:01:38 +0000 (UTC)
Raw View
"James Kuyper Jr." wrote:
>
> Pete Becker wrote:
> ....
> > Undoubtedly. But I don't think it's important to write code that is safe
> > for incompetent programmers.
>
> Why not? They're not exactly an endangered species.
>
> Note: in this context, to justify your objections, "incompetent
> programmers" would have to include anyone who's ever had a problem
> figuring out all of the intertwining implications of all the applicable
> documentation when writing a single line of code, even if that single
> line of code uses two dozen different classes from five different
> libraries that were not written to work together.

Nope. I used the term "incompetent programmers" in response to your
words, which you snipped:

> No - the ones dumb enough to rely on the compiler INSTEAD of thinking
> will continue do so, no matter how unreliable it is.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Sat, 7 Dec 2002 10:02:00 +0000 (UTC)
Raw View
Tom Hyer wrote:
>
> petebecker@acm.org (Pete Becker) wrote in message news:<3DED8110.6FF05730@acm.org>...
> >
> > The distinction to keep in mind is that between "if you do this my code
> > won't work" and "if you do this your code won't work." The former is why
> > you make things private. The latter is not your responsibility.
> >
>     But the former is never a reason to make something private.
>

Nonsense. That is exactly what private is for.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Sat, 7 Dec 2002 10:02:02 +0000 (UTC)
Raw View
Randy Maddox wrote:
>
> I also firmly agree with James Kuyper and others who state that the
> designer of a class is in a position to know better whether or not
> his/her class should be derived from.

Nobody has disputed this.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Sat, 7 Dec 2002 22:29:54 +0000 (UTC)
Raw View
In article <3DF147AE.855D4F9C@acm.org>, Pete Becker <petebecker@acm.org>
writes
>I take it you don't ever cross the street, because, after all, some
>drunk driver might come screeching around the corner and run you down.

If you will argue from analogy, many countries have laws about
jay-walking and require that you only cross roads at authorised crossing
points (they do not trust their citizens to know when it is OK to cross
at a place of their choosing).

Arterial roads usually have complete prohibitions against pedestrians
crossing them (you have to use a footbridge or an underpass.

Many places have barriers where footpaths join sidewalks to prevent the
careless pedestrian from overshooting the join and finishing up in the
path of oncoming traffic.

Of course pedestrians should read signs, but we know they do not always
do so.

What I am finding increasingly hard to understand is why you are so
adamantly against something that many want and that you would not be
required to use.

On the other hand, how much support time is taken up in explaining to
customers why there code that derives from something such as string or
vector fails? Particularly as such failures will often be subtle.


--
Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ 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: kuyper@wizard.net ("James Kuyper Jr.")
Date: Sat, 7 Dec 2002 22:30:34 +0000 (UTC)
Raw View
Pete Becker wrote:
> Tom Hyer wrote:
>
>>petebecker@acm.org (Pete Becker) wrote in message news:<3DED8110.6FF05730@acm.org>...
>>
>>>The distinction to keep in mind is that between "if you do this my code
>>>won't work" and "if you do this your code won't work." The former is why
>>>you make things private. The latter is not your responsibility.
>>>
>>
>>    But the former is never a reason to make something private.
>>
>
>
> Nonsense. That is exactly what private is for.

Can you provide an example? I can't remember ever using it for that
purpose, and I don't see how it could be used for that purpose.

---
[ 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: kuyper@wizard.net ("James Kuyper Jr.")
Date: Sat, 7 Dec 2002 22:30:40 +0000 (UTC)
Raw View
Pete Becker wrote:
....
> I've said three times now that it does not apply to private/protected

Yes, you have.

> and why.

I missed that; at least, I never saw you draw the distinction in any way
that actually worked.

You mentioned the distinction between what's needed to make your code
work, and what's needed to make other people's code work. That's not a
very clear distinction, since the whole issue only arises when both sets
of code have to work together. In any event, to the extent that the
distinction is clear, private/protected very clearly comes down on the
other side of fence; just like 'final', it's NEVER needed to make your
own code work.

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Sat, 7 Dec 2002 23:27:13 +0000 (UTC)
Raw View
Francis Glassborow wrote:
>
> What I am finding increasingly hard to understand is why you are so
> adamantly against something that many want and that you would not be
> required to use.

What I am adamantly against is  arrogance as a design principle,
simplistic analysis, and ad hominem arguments.

>
> On the other hand, how much support time is taken up in explaining to
> customers why there code that derives from something such as string or
> vector fails? Particularly as such failures will often be subtle.
>

Don't ask me: the folks who want to be able to block inheritance are the
ones who should have data on what its benefits would be. I asked the
same thing several days ago, in different words, and nobody has replied.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Sat, 7 Dec 2002 23:27:18 +0000 (UTC)
Raw View
"James Kuyper Jr." wrote:
>
> Pete Becker wrote:
> > Tom Hyer wrote:
> >
> >>petebecker@acm.org (Pete Becker) wrote in message news:<3DED8110.6FF05730@acm.org>...
> >>
> >>>The distinction to keep in mind is that between "if you do this my code
> >>>won't work" and "if you do this your code won't work." The former is why
> >>>you make things private. The latter is not your responsibility.
> >>>
> >>
> >>    But the former is never a reason to make something private.
> >>
> >
> >
> > Nonsense. That is exactly what private is for.
>
> Can you provide an example? I can't remember ever using it for that
> purpose, and I don't see how it could be used for that purpose.
>

class Array
{ // sketch only, of course
public:
 void append(int value) { data[count++] = value; }
private:
 int *data;
 int count;
};

Now, the reason you make 'count' private is that if it's public user
code can modify count in unpredictable ways, and then append will not do
what it is supposed to do.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kuyper@wizard.net ("James Kuyper Jr.")
Date: Sun, 8 Dec 2002 01:18:40 +0000 (UTC)
Raw View
Pete Becker wrote:
> "James Kuyper Jr." wrote:
>
>>Pete Becker wrote:
>>
>>>Tom Hyer wrote:
>>>
>>>
>>>>petebecker@acm.org (Pete Becker) wrote in message news:<3DED8110.6FF05730@acm.org>...
>>>>
>>>>
>>>>>The distinction to keep in mind is that between "if you do this my code
>>>>>won't work" and "if you do this your code won't work." The former is why
>>>>>you make things private. The latter is not your responsibility.
>>>>>
>>>>
>>>>   But the former is never a reason to make something private.
>>>>
>>>
>>>
>>>Nonsense. That is exactly what private is for.
>>
>>Can you provide an example? I can't remember ever using it for that
>>purpose, and I don't see how it could be used for that purpose.
>>
>
>
> class Array
> { // sketch only, of course
> public:
>  void append(int value) { data[count++] = value; }
> private:
>  int *data;
>  int count;
> };
>
> Now, the reason you make 'count' private is that if it's public user
> code can modify count in unpredictable ways, and then append will not do
> what it is supposed to do.

Which is needed only to make other people's code work. It doesn't make
your code work, because even if 'count' weren't private, you'd never do
something as stupid as changing 'count' from outside the append()
member. You know what 'count' means, and why it shouldn't be changed
that way. It's the correct behavior of other people's code (when it
calls yours) that you're protecting by marking 'count' as private.

---
[ 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: scottm@toast.net ("Scott Mayo")
Date: Sun, 8 Dec 2002 23:30:33 +0000 (UTC)
Raw View
"Pete Becker" <petebecker@acm.org> wrote in message
news:3DF27EB3.43A77440@acm.org...
> Francis Glassborow wrote:

> > What I am finding increasingly hard to understand is why you are so
> > adamantly against something that many want and that you would not be
> > required to use.

> What I am adamantly against is  arrogance as a design principle,
> simplistic analysis, and ad hominem arguments.

> > On the other hand, how much support time is taken up in explaining to
> > customers why there code that derives from something such as string or
> > vector fails? Particularly as such failures will often be subtle.

> Don't ask me: the folks who want to be able to block inheritance are the
> ones who should have data on what its benefits would be. I asked the
> same thing several days ago, in different words, and nobody has replied.

I have replied. I gave an example of a class which should be protected
against extension, and I gave general examples of the sorts of programmers
that would benefit from additional compiler hints in such cases. And people
have also drawn analogies to private and const, which seem to me to make
excellent sense. The feature seems to be simple to implement, a natural
fit with the language, and has direct precedent in a somewhat-related
language. And it can help in optimization.

The reality is that not all programmers are skilled, and sometimes class
designers, who hopefully are skilled, need to offer guidance to the users
of their designs. Experience also shows that sometimes guidance needs
to be enforceable. It's true in society (laws) and it's true in programming
(enforced constraints). Final seems to me to be in the same category
as const and private - is it arrogant to declare variables as private?
Final also hold a little promise as an optimization aid, and I don't know
about you but I can never have too many of those. I don't see a
down side, except for your fear that someone may use it
when they shouldn't; and I can think of a few constructs in C++ that
are already risky in that regard. If you removed everything abusable
from a language, not much would be left.

Anyway, I'm done with this thread. Unless someone decides to
implement it in a compiler and gathers some user reaction to it,
I don't think continuing to go on about it here is going to reveal
anything not already said.



---
[ 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: petebecker@acm.org (Pete Becker)
Date: Sun, 8 Dec 2002 23:45:59 +0000 (UTC)
Raw View
Scott Mayo wrote:
>
> "Pete Becker" <petebecker@acm.org> wrote in message
> news:3DF27EB3.43A77440@acm.org...
> > Francis Glassborow wrote:
>
> > > On the other hand, how much support time is taken up in explaining to
> > > customers why there code that derives from something such as string or
> > > vector fails? Particularly as such failures will often be subtle.
>
> > Don't ask me: the folks who want to be able to block inheritance are the
> > ones who should have data on what its benefits would be. I asked the
> > same thing several days ago, in different words, and nobody has replied.
>
> I have replied. I gave an example of a class which should be protected
> against extension, and I gave general examples of the sorts of programmers
> that would benefit from additional compiler hints in such cases.

That has nothing to do with Francis' question or with mine. Let me
repeat mine:

What concrete evidence is there that being able to prevent inheritance
improves program quality?

> And people
> have also drawn analogies to private and const, which seem to me to make
> excellent sense.

Yes, people have claimed that they are analogous. I disagree, and I've
explained why.

> The feature seems to be simple to implement, a natural
> fit with the language, and has direct precedent in a somewhat-related
> language. And it can help in optimization.
>
> The reality is that not all programmers are skilled,

Yup, that's what underlies this idea: everyone's incompetent except me,
so I should be able to tell them what to do.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Mon, 9 Dec 2002 00:27:59 +0000 (UTC)
Raw View
"James Kuyper Jr." wrote:
>
> Pete Becker wrote:
> > Scott Mayo wrote:
> >
> >>Realistically, a lot of us work with people for whom
> >>English is a second language. English documentation and
> >>even comments in the code don't always have much
> >>authority in such a setting, even when the will to do the
> >>right thing is present. But *everyone* understands
> >>compiler error messages.
> >>
> >
> >
> > If someone can't read the documentation then misusing inheritance is the
> > least of your worries. How are they going to write any code that uses
> > your class?
>
> "can't read" and "have difficulty reading" are two different things. I
> can assure you from personal experience that it is possible (but very
> difficult) to get useful work out of a team who aren't all fluent in the
> project's official language. In such an environment, compiler messages
> are at least as effective as documentation for conveying requirements.
>

In such an environment, is inappropriate use of inheritance among the
most serious coding errors?

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Mon, 9 Dec 2002 00:28:38 +0000 (UTC)
Raw View
"James Kuyper Jr." wrote:
>
> Pete Becker wrote:
> > Allan W wrote:
> >
> >>petebecker@acm.org (Pete Becker) wrote
> >>
> >>>Niklas Matthies wrote:
> >>>
> >>>>So why not do the same with other features like 'const' or 'private',
> >>>>just documenting it instead of declaring it within the language?
> >>>>
> >>>
> >>>The difference is between "my code won't work right if you do this" and
> >>>"your code won't work right if you do this." The former is your
> >>>responsibility. The latter is not.
> >>
> >>Which is which?
> ....
> >> Which one does it mean when I make a member private?
> >
> >
> > I don't know. Why did you make it private? I'd make it private if that
> > was necessary for the correct behavior of my class.
>
> How could it be necessary for the correct behavior of your class?

A class has a public interface that defines the operations that can be
performed on it. It uses private data to implement those operations. If
making the data public allows users to violate class invariants then
making it private is necessary for the correct behavior of the class.

> Code
> that never attempts anything inappropriate with the class won't work any
> differently with 'private' than it would have if that member were
> 'public'. It's not for causing correct behavior, but for preventing
> incorrect behavior. The incorrect behavior it prevents can't even occur
> as part of the class definition, since inside that definition there's no
> difference between 'public' and 'private'.

If that's what you think a class definition means, I'm not surprised
that you're confused.

>
> ....
> >>Why is this different? Why would asking the compiler to enforce that
> >>requirement be harmful?
> >>
> >
> >
> > I guess I'm just not presumptious enough to believe that I'm the best
> > judge of how other programmers should solve problems I've never seen.
>
> Except, of course, when you designate certain members of your classes
> private. By doing that, you're preventing those other programmers from
> solving problems you've never seen, by accessing those members.

Nope. I'm making sure that my code works correctly, by enforcing class
invariants.

> You feel
> presumptuous enough to make that decision for them, why not this other
> decision as well? I'm afraid I don't see the distinction.
>

Don't see it, or don't want to see it?

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kuyper@wizard.net ("James Kuyper Jr.")
Date: Mon, 9 Dec 2002 00:35:16 +0000 (UTC)
Raw View
Pete Becker wrote:
....
> Once again: the difference is between "my code won't work right if you
> do this" and "your code won't work right if you do this." You use
> private to enforce the first of these. The second is not your
> responsibility.

Surely you have 'first' and 'second' reversed? Can you show me any way
in which 'private' makes your own code work? As far as I can see, its
sole purpose is to make sure that other people's code works, by ensuring
that their code doesn't have inappropriate access to your class. Your
own code will never even attempt to make inappropriate access to your
class. Your in-class code isn't even affected by 'private'. Your out of
class code is written by the author of the class, and if there's anyone
who understands the limitations of your class better than you, there's a
serious problem somewhere.

---
[ 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: kuyper@wizard.net ("James Kuyper Jr.")
Date: Mon, 9 Dec 2002 00:35:31 +0000 (UTC)
Raw View
Pete Becker wrote:
> "James Kuyper Jr." wrote:
>
>>Pete Becker wrote:
>>....
>>
>>>Undoubtedly. But I don't think it's important to write code that is safe
>>>for incompetent programmers.
>>
>>Why not? They're not exactly an endangered species.
>>
>>Note: in this context, to justify your objections, "incompetent
>>programmers" would have to include anyone who's ever had a problem
>>figuring out all of the intertwining implications of all the applicable
>>documentation when writing a single line of code, even if that single
>>line of code uses two dozen different classes from five different
>>libraries that were not written to work together.
>
>
> Nope. I used the term "incompetent programmers" in response to your
> words, which you snipped:

I said "to justify your objections". Your latest comment may have
specifically referred only to those described below, but your earlier
objections make sense only if the category of programmers described
above is small.

>>No - the ones dumb enough to rely on the compiler INSTEAD of thinking
>>will continue do so, no matter how unreliable it is.

As I said, "not exactly an endangered species".

---
[ 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: comp.std.c++_2002-12-07@nmhq.net (Niklas Matthies)
Date: Mon, 9 Dec 2002 00:35:57 +0000 (UTC)
Raw View
On 2002-12-07 10:01, Pete Becker <petebecker@acm.org> wrote:
> Niklas Matthies wrote:
>>
>> On 2002-12-06 01:46, Pete Becker <petebecker@acm.org> wrote:
>> > Allan W wrote:
>> >> petebecker@acm.org (Pete Becker) wrote
>> >> > Niklas Matthies wrote:
>> >> > > So why not do the same with other features like 'const' or 'private',
>> >> > > just documenting it instead of declaring it within the language?
>> >> > >
>> >> >
>> >> > The difference is between "my code won't work right if you do this" and
>> >> > "your code won't work right if you do this." The former is your
>> >> > responsibility. The latter is not.
>> >>
>> >> Which is which?
>> >>
>> >> When I write a class that has const members, am I saying "my code won't
>> >> work right if you change this" or "your code won't work right if you
>> >> change this?"
>> >
>> > I don't know. Why did you make it const? I'd make it const if that was
>> > necessary for the correct behavior of my class.
>> >
>> >>  Which one does it mean when I make a member private?
>> >
>> > I don't know. Why did you make it private? I'd make it private if that
>> > was necessary for the correct behavior of my class.
>>
>> It is never strictly necessary to make something a member const or
>> private for the correct behavior of the class. It is merely necessary
>> that client code doesn't do certain things with those members. You could
>> as well specify this in the class' documentation if you expect users of
>> the class to diligently read and adhere to this documentation, as you
>> apparently do with regard to derivation.
>
> Once again: the difference is between "my code won't work right if you
> do this" and "your code won't work right if you do this." You use
> private to enforce the first of these. The second is not your
> responsibility.

One part of our disagreement is that I do not agree that derivation
doesn't (also) fall into the first case. When you derive from some
class, you are putting the code of the base class in a situation were
it might not work as intended any more.

What you seem to say is that, as soon as someone derives from a class,
the author of the base class is not responsible anymore of the behavior
of the base class' code. The same could be said for accessing members
documented as private, or passing parameters with values declared
invalid by the documentation. In all of these cases code is being
mis-used by some client code.

What exactly is the fundamental difference you seem to see, that goes
beyond an arbitrary convention? Continuing to repeat the above like a
mantra doesn't really explain anything.

-- Niklas Matthies

---
[ 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: fjh@cs.mu.OZ.AU (Fergus Henderson)
Date: Mon, 9 Dec 2002 18:30:35 +0000 (UTC)
Raw View
fonseca@mip.sdu.dk writes:

>Some additional notes which I think passed you all by.
>
>1. Inheritance may be blocked by making all constructors private.

That works in some cases, but it has significant drawbacks which make
it infeasible in very many cases, and generally undesirable.

In particular, in very many cases you need to have a copy constructor.

Also, sometimes a default constructor is needed for compatibility
with library routines such as those in the STL.

Also, even in the cases where it works, it would be cumbersome.
And it's not concise.  "final" would provide concise, clear
documentation whose value is improved because its validity is checked
by the compiler.

So this would be no substitute for "final".

--
Fergus Henderson <fjh@cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.

---
[ 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: kuyper@wizard.net ("James Kuyper Jr.")
Date: Mon, 9 Dec 2002 18:30:53 +0000 (UTC)
Raw View
Pete Becker wrote:
....
> If youblet users arbitrarily change the contents of your class then the
> code you wrote to implement your class won't work right.

The same is true, in some circumstances, if you let users arbitrarily
derive from your 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kuyper@wizard.net ("James Kuyper Jr.")
Date: Mon, 9 Dec 2002 18:30:53 +0000 (UTC)
Raw View
Pete Becker wrote:
> "James Kuyper Jr." wrote:
....
> A class has a public interface that defines the operations that can be
> performed on it. It uses private data to implement those operations. If
> making the data public allows users to violate class invariants then
> making it private is necessary for the correct behavior of the class.

So? Document the restriction, and the only people who'll misuse it are
the same people who'll misuse the classes that shouldn't be derived
from: those who don't always read, or don't always understand, the
documentation.


>>Code
>>that never attempts anything inappropriate with the class won't work any
>>differently with 'private' than it would have if that member were
>>'public'. It's not for causing correct behavior, but for preventing
>>incorrect behavior. The incorrect behavior it prevents can't even occur
>>as part of the class definition, since inside that definition there's no
>>difference between 'public' and 'private'.
>
>
> If that's what you think a class definition means, I'm not surprised
> that you're confused.

I'd appreciate you explaining what you think I've misunderstood about a
"class definition". I've reviewed my statement above, and the only
corrections I can find to make to it seem unlikely to be what you're
referring to. I'd correct "can't even occur as part of" to "can't even
be prevented inside of". Also, when I said "as part of the class
definition", I meant to include the definition of the classes member
functions, even if they aren't defined in-class.

....
> Nope. I'm making sure that my code works correctly, by enforcing class
> invariants.

And how is that different from making sure that your code works
correctly by preventing it from being derived from?

>>You feel
>>presumptuous enough to make that decision for them, why not this other
>>decision as well? I'm afraid I don't see the distinction.
>>
>
>
> Don't see it, or don't want to see it?

Both. I don't want to see it, because I don't want to delude myself by
seeing things that aren't really there.




---
[ 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: kuyper@wizard.net ("James Kuyper Jr.")
Date: Mon, 9 Dec 2002 18:31:13 +0000 (UTC)
Raw View
Pete Becker wrote:
....
> Okay, it's clear that your goal is to disagree, not to understand.
> There's no point in continuing this discussion.

No :-) my goal is not to disagree. In fact, I'll prove that, by agreeing
with you that there's no point in continuing this discussion. I've
posted several responses this morning before reading this particular
message, but I'm willing for this to be my last message on the topic, if
that's your last message on the topic.

---
[ 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: kanze@gabi-soft.de (James Kanze)
Date: Mon, 9 Dec 2002 18:31:47 +0000 (UTC)
Raw View
fjh@cs.mu.OZ.AU (Fergus Henderson) wrote in message
news:<at1m86$mj5$1@mulga.cs.mu.OZ.AU>...
> petebecker@acm.org (Pete Becker) writes:
> >"James Kuyper Jr." wrote:
> >> Pete Becker wrote:
> >> > Now, the reason you make 'count' private is that if it's public
> >> > user code can modify count in unpredictable ways, and then append
> >> > will not do what it is supposed to do.

> >> Which is needed only to make other people's code work. It doesn't
> >> make your code work, because even if 'count' weren't private, you'd
> >> never do something as stupid as changing 'count' from outside the
> >> append() member.

> >Okay, it's clear that your goal is to disagree, not to understand.
> >There's no point in continuing this discussion.

> Accusing an individual of bad motives ("your goal is to disagree") is
> an ad hominem attack, which IMHO should not have been allowed by the
> moderators.  I hope that you will retract it.

I think both sides are overreacting somewhat.  I rather favor final, on
the grounds that if it is added to the standard, I can expect every C++
programmer to understand it, where as if I write "Il ne faut pas h   riter
de cette classe", I imagine that there are some programmers who won't
understand it. (Of course, most of the time, they won't understand
enough to use the class in any way, much less to start thinking about
inheriting from it, but there might be exceptions.)

On the other hand, I find it slightly ridiculous comparing final to
private.  Before I learned C++, I worked in C.  I defined struct's, and
a series of functions to manipulate them, and I crossed my fingers that
no one accessed them except through my functions.  I jumped on C++
without knowing the least thing about object orientation, because
private (and constructors and destructors) filled an immediate and
strongly felt need in my C programming.

I've now been working in C++ for well over ten years.  While I sort of
feel that final would be a nice thing, it's certainly not something
essential, and I can't say that I've suffered from its lack in those ten
years.  Private is a must have for any serious language.  Final is a
nice to have, but it certainly isn't a killer criteron, and I can live
pretty well without it, too.

In the end, I pretty much agree with what Pete Becker is saying.  Except
that I don't see it as a very strong argument not to have final -- he's
effectively proven that final isn't necessary (but we knew that all
along), but not that it wouldn't be useful.  And nobody has address the
costs/benefits issue: off hand, I expect that the cost would be very
low, so even a moderate amount of benefit (much less than private) would
suffice.

--
James Kanze                           mailto:jkanze@caicheuvreux.com
Conseils en informatique orient   e objet/
                    Beratung in objektorientierter Datenverarbeitung

---
[ 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: gdr@integrable-solutions.net (Gabriel Dos Reis)
Date: Mon, 9 Dec 2002 18:58:36 +0000 (UTC)
Raw View
fjh@cs.mu.OZ.AU (Fergus Henderson) writes:

[...]

| Why should the bar be set higher for this feature than for other C++ features?

I don't have the impression that the bar is being set higher for this
feature than for other C++ functionalities.

--
Gabriel Dos Reis,               gdr@integrable-solutions.net

---
[ 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: pdimov@mmltd.net (Peter Dimov)
Date: Mon, 9 Dec 2002 20:09:42 +0000 (UTC)
Raw View
fjh@cs.mu.OZ.AU (Fergus Henderson) wrote in message news:<at1m86$mj5$1@mulga.cs.mu.OZ.AU>...
[...]
> It seems clear to me that both "private" and "final" can be used
> to enforce invariants.  "private" can be used to enforce the invariant
> that a private data member has not been modified by code outside the
> class.  "final" can be used to enforce the invariant that a pointer
> points to a base class object, not a derived object.
>
> Consider, for example, a swap() member:
>
>  /* final */ class Array
>  {     // sketch only, of course
>  public:
>        void swap(Array &x) {
>           std::swap(data, x.data);
>    std::swap(count, x.count);
>        }
>        void append(int value) { data[count++] = value; }
>  private:
>        int *data;
>        int count;
>  };
>
> Here the correctness of `append' relies on the validity of the `count'
> member, which is enforced by the use of "private".  Likewise, the correctness
> of the `swap' member function relies on the validity of the `x' and `this'
> parameters, which must each point to an object of class `Array', not a
> derived class.  This could be enforced by the use of "final" on the
> Array class.

- The same principle applies to operator=. Why did you choose swap as
an example?

- Changing a private member typically would unconditionally break the
class invariant. Derivation from the class does not break any
invariants. Calling swap() with an operand that is not an Array would;
therefore, you should strive to find the error at the point where
swap() is erroneously called, not at the point of derivation.

---
[ 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: Mon, 9 Dec 2002 20:23:01 +0000 (UTC)
Raw View
Francis Glassborow wrote:

>  swap() is only one example of a function that sometimes
> relies on an invariant.

If someone really wants a final swap, why was it made
virtual to begin with?

---
[ 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: brangdon@cix.co.uk (Dave Harris)
Date: Mon, 9 Dec 2002 20:23:12 +0000 (UTC)
Raw View
hyrosen@mail.com (Hyman Rosen) wrote (abridged):
> > We would like foo() to be dynamically dispatched in the first
> > template instantiation, and statically in the second, without having
> > to rewrite the template.
>
> And since simple templates like this are inlined, and you have
> a Base reference but a Derived object, that's exactly what will
> happen!

I think your comment is more pedantic than constructive. That optimisation
has nothing to do with the point under discussion. We can probably avoid
it by changing the example to:

   void test( Derived &d ) {
        Base &b = d;
        demo( b );
        demo( d );
    }

-- as I am sure you knew. Now d is a reference, perhaps to a subclass of
Derived.


>  > Functions which are virtual in the base class cannot be made
>  > non-virtual in the derived class, even though this is often desired.
>
> But why is this desired? Obviously, making methods non-virtual in the
> derived class only affects direct calls to objects of the derived class.

It also affects calls through references and pointers to the derived
class (and classes derived in turn from that).


> In that case, there is no reason not to use another name for the "final"
> method.

A reason, as I have just explained, is compile-time polymorphism.
Templates are one example. Even without templates, we may not want to
hand-edit megabytes of code looking for places where foo() can be changed
to final_foo().


  Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
      brangdon@cix.co.uk      |   And close your eyes with holy dread,
                              |  For he on honey dew hath fed
 http://www.bhresearch.co.uk/ |   And drunk the milk of Paradise."

---
[ 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: terekhov@web.de (Alexander Terekhov)
Date: Mon, 9 Dec 2002 20:23:20 +0000 (UTC)
Raw View
Francis Glassborow wrote:
[...]
> swap() is only one example of a function that sometimes relies on an
> invariant.

Frankly, I didn't catch the meaning [in favor of blocking inheritance]
of that example. Anyway, are you going to prohibit *private* inheritance
for classes "sealed" with the upcoming final-thing?

regards,
alexander.

---
[ 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: Mon, 9 Dec 2002 22:14:32 +0000 (UTC)
Raw View
Dave Harris wrote:

>  Now d is a reference, perhaps to a subclass of Derived.

OK, but we can also amend the template:

     template <typename T> void demo( T &t ) { t.foo(); }
     template <> void demo(Derived &t) { t.Derived::foo(); }

You can now riposte with the objection that there could be many
such templates, and they would all have to be specialized. But
how much real code out there needs this? (One possibility -
specialized streambufs, which override overflow and underflow,
and would like to be efficient. Experts?)

> Even without templates, we may not want to hand-edit megabytes

> of code looking for places where foo() can be changed to final_foo().


But without templates, all those places must be written in terms of
base objects. None of them could be so changed!

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Tue, 10 Dec 2002 00:46:57 +0000 (UTC)
Raw View
Randy Maddox wrote:
>
> several have argued very strongly that compiler
> support for the concept of a class not intended to be derived from is
> somehow very wrong.

I haven't seen anyone say this. Can you cite an example?

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Tue, 10 Dec 2002 01:31:47 +0000 (UTC)
Raw View
Francis Glassborow wrote:
>
> The only arguments that I would accept against providing 'final' + a
> mechanism for over-riding it would be that its implementation had
> serious impact on the semantics of C++.
>

The final-is-just-like-private folks haven't jumped in to claim that
being able to override final means we should also be able to override
private. Could it be that private and final are different when that
distinction supports a position they like?

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Tue, 10 Dec 2002 01:32:03 +0000 (UTC)
Raw View
Francis Glassborow wrote:
>
> The only arguments that I would accept against providing 'final' + a
> mechanism for over-riding it would be that its implementation had
> serious impact on the semantics of C++.
>

One of the reasons given in this discussion for final was that it could
provide optimization opportunities for the compiler. Making it
overridable precludes this.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Tue, 10 Dec 2002 05:19:31 +0000 (UTC)
Raw View
"James Kuyper Jr." wrote:
>
> Pete Becker wrote:
> ....
> > If youblet users arbitrarily change the contents of your class then the
> > code you wrote to implement your class won't work right.
>
> The same is true, in some circumstances, if you let users arbitrarily
> derive from your class.
>

Nice claim. Do you have code to demonstrate it?

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: nid_oizo@yahoo.com_removethe_ (Nicolas Fleury)
Date: Tue, 10 Dec 2002 05:19:31 +0000 (UTC)
Raw View
Pete Becker wrote:
>
> That has nothing to do with Francis' question or with mine. Let me
> repeat mine:
>
> What concrete evidence is there that being able to prevent inheritance
> improves program quality?
>

Suppose for example your have a class A and a derived class B.  The way
B is designed, it should not be derived and you document that.  You
provide a container of A.  Somebody doesn't see the documentation and
derive a class C from B.  After, someone comes to you and tell you your
container of A is buggy (because there's some C objects in it).

I doesn't happen often you need a final keyword, but when you need it,
it do improves software quality.

C++ is a language that provides many features to detect errors at
compile-time instead of at run-time.  A final-like feature seems to me
suitable for C++.

I don't know what is your development environment, but I can assure you
that in mine a final-like feature would be a good thing.


Regards,

Nicolas Fleury

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Tue, 10 Dec 2002 05:19:37 +0000 (UTC)
Raw View
Fergus Henderson wrote:
>
> petebecker@acm.org (Pete Becker) writes:
>
> >What concrete evidence is there that being able to prevent inheritance
> >improves program quality?
>
> What concrete evidence is there that *any* C++ feature improves
> program quality?

There's a great deal of history showing that access protection improves
code quality. There's a great deal of history showing that structured
programming improves code quality.

>
> Being able to prevent inheritence means that certain kinds of preconditions,
> whose violation would lead to program bugs, can easily be statically enforced.
> That's a fact.
>

Irrelevant, unless you can show that those cases matter in practice.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: allan_w@my-dejanews.com (Allan W)
Date: Tue, 10 Dec 2002 05:20:00 +0000 (UTC)
Raw View
> > Pete Becker <petebecker@acm.org> wrote:
> > > The programmer is in a better position to know what he needs than the
> > > author of the class. Writing a class shouldn't turn you into a nanny.

> Niklas Matthies wrote:
> > Why not? It's your class, after all.

petebecker@acm.org (Pete Becker) wrote
> Yup, that's the bottom line, isn't it? Doesn't what users want; you
> wrote it, you decide what others can do with it.

Can I assume that your work at Dinkumware is neither in design nor
in sales?

Personally, my own philosophy about software creation has been: give
my clients/users/customers what they want, and be sure it works.

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Tue, 10 Dec 2002 05:20:10 +0000 (UTC)
Raw View
Fergus Henderson wrote:
>
> petebecker@acm.org (Pete Becker) writes:
>
> >Unless you're the user's mother it's not
> >your responsibility to try to make him into a better programmer.
>
> It is every class designer's responsibility to do their best
> to ensure that the classes that they design are easy to use,
> and hard to misuse.

That was the goal of Pascal. Look how well it's succeeded.

>
> Doing this won't make the users of the class better programmers,
> but it may well make them produce better programs.
>

How many program failures do you know of that have resulted from
inappropriate inheritance and could have been prevented by blocking
inheritance?

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Wed, 4 Dec 2002 20:02:42 +0000 (UTC)
Raw View
Hyman Rosen wrote:
> Remember that C++, unlike Java, has non-virtual methods, and so
> doesn't really need a keyword which says to cut off virtuality.

And I should add that C++, unlike Java, has actual objects instead
of only pointers to objects, so again the compiler does not need
help to cut off virtuality when you're making a call that way.

---
[ 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: comp.std.c++_2002-12-04@nmhq.net (Niklas Matthies)
Date: Thu, 5 Dec 2002 00:39:21 +0000 (UTC)
Raw View
On 2002-12-04 16:53, Pete Becker <petebecker@acm.org> wrote:
> "James Kuyper Jr." wrote:
>> Pete Becker wrote:
>>  > Doesn't matter. Document that B isn't intended to be derived from.
>>  > You're done with your work.
>>
>> Documentation is all very well and good; but compile-time error messages
>> when someone attempts to extend a class that's not meant to be extended
>> are better.
>
> Someone who derives from a class without reading the documentation is a
> loose cannon. Compile-time error messages could prevent this derivation,
> but don't address the underlying problem. Fix the real problem, not the
> symptom.

So why not do the same with other features like 'const' or 'private',
just documenting it instead of declaring it within the language?

-- Niklas Matthies

---
[ 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: kuyper@wizard.net ("James Kuyper Jr.")
Date: Thu, 5 Dec 2002 06:29:17 +0000 (UTC)
Raw View
Pete Becker wrote:
> "James Kuyper Jr." wrote:
....
>>Documentation is all very well and good; but compile-time error messages
>>when someone attempts to extend a class that's not meant to be extended
>>are better.
>>
>
>
> Someone who derives from a class without reading the documentation is a
> loose cannon. Compile-time error messages could prevent this derivation,
> but don't address the underlying problem. Fix the real problem, not the
> symptom.

Fixing the real problem is a great idea, and reasonable efforts should
be made in that direction. That doesn't make it any less useful to also
trigger alerts when the symptom comes up. This isn't "fixing the
symptom", it's "detecting the problem". That's equally true whether you
see the problem as "extending a class that's not meant to be extended"
or "failing to read the documentation".

That's particularly true since I'm doubtful that we can ever completely
fix the real problem. Human beings are fallible, programmers who do
everything that a good programmer should do are rare (I've certainly
never met one) and correspondingly expensive, and budgets are tight.

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Thu, 5 Dec 2002 07:07:48 +0000 (UTC)
Raw View
Niklas Matthies wrote:
>
> On 2002-12-04 16:53, Pete Becker <petebecker@acm.org> wrote:
> > "James Kuyper Jr." wrote:
> >> Pete Becker wrote:
> >>  > Doesn't matter. Document that B isn't intended to be derived from.
> >>  > You're done with your work.
> >>
> >> Documentation is all very well and good; but compile-time error messages
> >> when someone attempts to extend a class that's not meant to be extended
> >> are better.
> >
> > Someone who derives from a class without reading the documentation is a
> > loose cannon. Compile-time error messages could prevent this derivation,
> > but don't address the underlying problem. Fix the real problem, not the
> > symptom.
>
> So why not do the same with other features like 'const' or 'private',
> just documenting it instead of declaring it within the language?
>

The difference is between "my code won't work right if you do this" and
"your code won't work right if you do this." The former is your
responsibility. The latter is not.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: scottm@toast.net ("Scott Mayo")
Date: Thu, 5 Dec 2002 18:11:06 +0000 (UTC)
Raw View
"Pete Becker" <petebecker@acm.org> wrote in message
news:3DEEA51B.EA2D1066@acm.org...
> Niklas Matthies wrote:

> > So why not do the same with other features like 'const' or 'private',
> > just documenting it instead of declaring it within the language?

> The difference is between "my code won't work right if you do this" and
> "your code won't work right if you do this." The former is your
> responsibility. The latter is not.

*blink*

And you can get your management to understand that?

Give me 'final'. Give me anything that will let me have
the *compiler* require that people follow the rules I
set down when I designed my classes, especially if it
also has a shot of improving optimizations.

Realistically, a lot of us work with people for whom
English is a second language. English documentation and
even comments in the code don't always have much
authority in such a setting, even when the will to do the
right thing is present. But *everyone* understands
compiler error messages. Admittedly I'd be happier
if the standard required compilers to hit people with
rubber mallets when they tried to violate design
constraints, but an error message is a start.

--
I suppose the rubber mallet thing wouldn't work. Evolution
would simply select for people who liked being hit with
hammers, and programming would be no better off than
it is today.



---
[ 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: petebecker@acm.org (Pete Becker)
Date: Thu, 5 Dec 2002 18:11:31 +0000 (UTC)
Raw View
"James Kuyper Jr." wrote:
>
> Pete Becker wrote:
> > "James Kuyper Jr." wrote:
> ....
> >>Documentation is all very well and good; but compile-time error messages
> >>when someone attempts to extend a class that's not meant to be extended
> >>are better.
> >>
> >
> >
> > Someone who derives from a class without reading the documentation is a
> > loose cannon. Compile-time error messages could prevent this derivation,
> > but don't address the underlying problem. Fix the real problem, not the
> > symptom.
>
> Fixing the real problem is a great idea, and reasonable efforts should
> be made in that direction. That doesn't make it any less useful to also
> trigger alerts when the symptom comes up.

It encourages hacking, under the false belief that the compiler will
catch mistakes.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Thu, 5 Dec 2002 18:23:24 +0000 (UTC)
Raw View
Scott Mayo wrote:
>
> "Pete Becker" <petebecker@acm.org> wrote in message
> news:3DEEA51B.EA2D1066@acm.org...
> > Niklas Matthies wrote:
>
> > > So why not do the same with other features like 'const' or 'private',
> > > just documenting it instead of declaring it within the language?
>
> > The difference is between "my code won't work right if you do this" and
> > "your code won't work right if you do this." The former is your
> > responsibility. The latter is not.
>
> *blink*
>
> And you can get your management to understand that?
>

Yes.

> Give me 'final'. Give me anything that will let me have
> the *compiler* require that people follow the rules I
> set down when I designed my classes, especially if it
> also has a shot of improving optimizations.
>

Why do you think you're better qualified to judge the code that someone
else is writing than they are?

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: comp.std.c++_2002-12-05@nmhq.net (Niklas Matthies)
Date: Thu, 5 Dec 2002 18:43:31 +0000 (UTC)
Raw View
On 2002-12-05 07:07, Pete Becker <petebecker@acm.org> wrote:
> Niklas Matthies wrote:
>> On 2002-12-04 16:53, Pete Becker <petebecker@acm.org> wrote:
>> > "James Kuyper Jr." wrote:
>> >> Pete Becker wrote:
>> >>  > Doesn't matter. Document that B isn't intended to be derived from.
>> >>  > You're done with your work.
>> >>
>> >> Documentation is all very well and good; but compile-time error messages
>> >> when someone attempts to extend a class that's not meant to be extended
>> >> are better.
>> >
>> > Someone who derives from a class without reading the documentation is a
>> > loose cannon. Compile-time error messages could prevent this derivation,
>> > but don't address the underlying problem. Fix the real problem, not the
>> > symptom.
>>
>> So why not do the same with other features like 'const' or 'private',
>> just documenting it instead of declaring it within the language?
>
> The difference is between "my code won't work right if you do this" and
> "your code won't work right if you do this." The former is your
> responsibility. The latter is not.

If "your code" is client code of "my code", then the former implies the
latter. Currently, instead of using 'final', we have to say in the docs
"if you use my code in the context of a derived class, it probably won't
work right, so don't do this". There isn't a fundamental difference to
"my code won't work right if you do this" here.

-- Niklas Matthies

---
[ 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: comp.std.c++_2002-12-05@nmhq.net (Niklas Matthies)
Date: Thu, 5 Dec 2002 18:53:50 +0000 (UTC)
Raw View
On 2002-12-05 18:23, Pete Becker <petebecker@acm.org> wrote:
> Scott Mayo wrote:
[...]
>> Give me 'final'. Give me anything that will let me have
>> the *compiler* require that people follow the rules I
>> set down when I designed my classes, especially if it
>> also has a shot of improving optimizations.
>
> Why do you think you're better qualified to judge the code that someone
> else is writing than they are?

With regard to derivation, the question is who is better qualified to
judge whether a class should or shouldn't be derived from: The author of
said class, or the programmer who merely wants to use that class as a
base for his own? I believe that the author of a class is well justified
if he decides that the users of his class are likely to not be better
qualified than himself as the author of the class. If a user disagrees,
he can go and create his own classes to derive from.

-- Niklas Matthies

---
[ 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: kuyper@wizard.net ("James Kuyper Jr.")
Date: Thu, 5 Dec 2002 19:23:10 +0000 (UTC)
Raw View
Pete Becker wrote:
> "James Kuyper Jr." wrote:
....
>>Fixing the real problem is a great idea, and reasonable efforts should
>>be made in that direction. That doesn't make it any less useful to also
>>trigger alerts when the symptom comes up.
>
>
> It encourages hacking, under the false belief that the compiler will
> catch mistakes.

That belief isn't false; the compiler will catch mistakes - sometimes.
The false belief is that it will catch all mistakes; you're not going to
eliminate that belief by increasing the number of mistakes it doesn't
catch. Anybody stupid enough to hold that belief isn't paying attention
to the evidence anyway. All you do by not catching a catchable mistake
is letting that mistake cause more problems than it would have caused if
it had been caught.

---
[ 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: Ken@Alverson.net ("Ken Alverson")
Date: Thu, 5 Dec 2002 19:23:18 +0000 (UTC)
Raw View
"Pete Becker" <petebecker@acm.org> wrote in message
news:3DEF561E.8938CBDA@acm.org...
> "James Kuyper Jr." wrote:
> >
> > Fixing the real problem is a great idea, and reasonable efforts
should
> > be made in that direction. That doesn't make it any less useful to
also
> > trigger alerts when the symptom comes up.
>
> It encourages hacking, under the false belief that the compiler will
> catch mistakes.

No more than an airbag encourages wrecking your car, under the false
belief that the airbag will save your life.

Just because an airbag doesn't work 100% of the time isn't a reason to
go without.  Similarly, avoiding safety features in a language because
they might encourage complacency doesn't strike me as a strong argument.
The same argument could be made for typesafety.  People could get too
comfortable with the compiler catching their type mistakes, so lets go
with void pointers and really good documentation.

Ken


---
[ 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: petebecker@acm.org (Pete Becker)
Date: Thu, 5 Dec 2002 19:43:45 +0000 (UTC)
Raw View
Niklas Matthies wrote:
>
> On 2002-12-05 18:23, Pete Becker <petebecker@acm.org> wrote:
> > Scott Mayo wrote:
> [...]
> >> Give me 'final'. Give me anything that will let me have
> >> the *compiler* require that people follow the rules I
> >> set down when I designed my classes, especially if it
> >> also has a shot of improving optimizations.
> >
> > Why do you think you're better qualified to judge the code that someone
> > else is writing than they are?
>
> With regard to derivation, the question is who is better qualified to
> judge whether a class should or shouldn't be derived from: The author of
> said class, or the programmer who merely wants to use that class as a
> base for his own?

The programmer who "merely" wants to derive from that class knows what
he wants to use it for. The author of the class does not. The programmer
is in a better position to know what he needs than the author of the
class. Writing a class shouldn't turn you into a nanny.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Thu, 5 Dec 2002 19:51:09 +0000 (UTC)
Raw View
Niklas Matthies wrote:
>
> On 2002-12-05 07:07, Pete Becker <petebecker@acm.org> wrote:
> > Niklas Matthies wrote:
> >> On 2002-12-04 16:53, Pete Becker <petebecker@acm.org> wrote:
> >> > "James Kuyper Jr." wrote:
> >> >> Pete Becker wrote:
> >> >>  > Doesn't matter. Document that B isn't intended to be derived from.
> >> >>  > You're done with your work.
> >> >>
> >> >> Documentation is all very well and good; but compile-time error messages
> >> >> when someone attempts to extend a class that's not meant to be extended
> >> >> are better.
> >> >
> >> > Someone who derives from a class without reading the documentation is a
> >> > loose cannon. Compile-time error messages could prevent this derivation,
> >> > but don't address the underlying problem. Fix the real problem, not the
> >> > symptom.
> >>
> >> So why not do the same with other features like 'const' or 'private',
> >> just documenting it instead of declaring it within the language?
> >
> > The difference is between "my code won't work right if you do this" and
> > "your code won't work right if you do this." The former is your
> > responsibility. The latter is not.
>
> If "your code" is client code of "my code", then the former implies the
> latter.

No, it doesn't.

> Currently, instead of using 'final', we have to say in the docs
> "if you use my code in the context of a derived class, it probably won't
> work right, so don't do this".

If it probably won't work right then there are cases in which it will
work right. Why do you want to prevent users of your class from using it
in those cases?

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: pavel_vozenilek@yahoo.co.uk (Pavel Vozenilek)
Date: Tue, 3 Dec 2002 05:39:56 +0000 (UTC)
Raw View
Avi Kak <kak@purdue.edu> wrote in message news:<3DDE59BD.14E86075@purdue.edu>...
> Hello:
>
[snip]
>   The issue I am pursuing is whether C++ has an equivalent
>   for the keyword "final" in Java
[snip]

http://www.research.att.com/~bs/bs_faq2.html#no-derivation solution
from Bjarne Stroustrup, legal but a bit clumsy.

http://groups.google.com/groups?q=author:pavel_vozenilek%40yahoo.co.uk&hl=en&lr=&ie=UTF-8&selm=731020ca.0211071225.2a3adea8%40posting.google.com&rnum=4
non-standard trick working for some compilers.

I don't know something as clean as Java final also valid in standard
C++.

/Pavel

---
[ 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: Tue, 3 Dec 2002 16:13:05 +0000 (UTC)
Raw View
Avi Kak wrote:
>   I do realize that a class can be made non-extendible

I still don't know what it is about programming that makes
people want to forcibly take away other people's freedom.
Give your class a non-virtual destructor, and be done with 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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: loic.actarus.joly@wanadoo.fr (=?ISO-8859-1?Q?Lo=EFc_Joly?=)
Date: Tue, 3 Dec 2002 23:50:20 +0000 (UTC)
Raw View
Hyman Rosen wrote:
> Avi Kak wrote:
>=20
>>   I do realize that a class can be made non-extendible
>=20
>=20
> I still don't know what it is about programming that makes
> people want to forcibly take away other people's freedom.
> Give your class a non-virtual destructor, and be done with it!
>=20

If you have
class A
{
   virtual ~A() {...}
   ...
};

class B : public A
{
};

And you want to tell : Ok, class A was extensible, but now, with class=20
B, i am done with my work, and class B should not be extensible, then=20
your proposal won't work.

--=20
Lo=EFc



---
[ 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: scottm@toast.net ("Scott Mayo")
Date: Wed, 4 Dec 2002 04:01:21 +0000 (UTC)
Raw View
"Hyman Rosen" <hyrosen@mail.com> wrote in message
news:1038924514.151952@master.nyc.kbcfp.com...
> Avi Kak wrote:

> >   I do realize that a class can be made non-extendible

> I still don't know what it is about programming that makes
> people want to forcibly take away other people's freedom.

When I'm coding for myself, or for people I trust, everything is open and
public: for development, and at the end when I'm certain I understand
how the class is to be used, I'll sling in some tighter restrictions. Not
really
to limit freedoms; but mostly in the vain hope that the compiler can
find more optimizations if the code use is more restricted.

When I'm coding for co-workers in a large company, who may or
may not be to find their way out of a soggy paper bag with pre-stressed
seams, a flashlight and a sharp knife, I start with everything private:, and
I try
to keep as much as possible that way. Programmers are idiots (I know,
being one) and will do idiotic things. Taking all the sharp pointy internal
implementation details of a class out of their hands is simply a way to
prevent
them from bleeding to death, making a mess, wasting everyone's time, and
diminishing everyone's paycheck (specifically, mine).

If someone needs to get access to an implementation detail I've
made private, or a class I've locked down, they know how to
modify source. Then what they do is their problem, not mine, and
I can point to their changes in the source control system and prove it.

God bless private:. God bless Stroustrup.



---
[ 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: allan_w@my-dejanews.com (Allan W)
Date: Wed, 4 Dec 2002 04:01:34 +0000 (UTC)
Raw View
> Avi Kak wrote:
> >   I do realize that a class can be made non-extendible

hyrosen@mail.com (Hyman Rosen) wrote
> I still don't know what it is about programming that makes
> people want to forcibly take away other people's freedom.
> Give your class a non-virtual destructor, and be done with it!

You can take that too far. Apply that logic overzealously, and
you'll never use "private" or "protected" in a class.

If a class is well-designed, it can be used in ways that the
original author never heard of. But if those uses make internal
design decisions fragile, you've gone too far. Sometimes less
is more.

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Wed, 4 Dec 2002 04:01:54 +0000 (UTC)
Raw View
Lo=EFc Joly wrote:
>=20
> Hyman Rosen wrote:
> > Avi Kak wrote:
> >
> >>   I do realize that a class can be made non-extendible
> >
> >
> > I still don't know what it is about programming that makes
> > people want to forcibly take away other people's freedom.
> > Give your class a non-virtual destructor, and be done with it!
> >
>=20
> If you have
> class A
> {
>    virtual ~A() {...}
>    ...
> };
>=20
> class B : public A
> {
> };
>=20
> And you want to tell : Ok, class A was extensible, but now, with class
> B, i am done with my work, and class B should not be extensible, then
> your proposal won't work.
>=20

Doesn't matter. Document that B isn't intended to be derived from.
You're done with your work.

--=20
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Wed, 4 Dec 2002 04:16:01 +0000 (UTC)
Raw View
Allan W wrote:
>
> > Avi Kak wrote:
> > >   I do realize that a class can be made non-extendible
>
> hyrosen@mail.com (Hyman Rosen) wrote
> > I still don't know what it is about programming that makes
> > people want to forcibly take away other people's freedom.
> > Give your class a non-virtual destructor, and be done with it!
>
> You can take that too far. Apply that logic overzealously, and
> you'll never use "private" or "protected" in a class.
>
> If a class is well-designed, it can be used in ways that the
> original author never heard of. But if those uses make internal
> design decisions fragile, you've gone too far. Sometimes less
> is more.
>

The distinction to keep in mind is that between "if you do this my code
won't work" and "if you do this your code won't work." The former is why
you make things private. The latter is not your responsibility.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kuyper@wizard.net ("James Kuyper Jr.")
Date: Wed, 4 Dec 2002 05:36:06 +0000 (UTC)
Raw View
Pete Becker wrote:
 > Lo=EFc Joly wrote:
 >
....
 >>If you have
 >>class A
 >>{
 >>   virtual ~A() {...}
 >>   ...
 >>};
 >>
 >>class B : public A
 >>{
 >>};
 >>
 >>And you want to tell : Ok, class A was extensible, but now, with class
 >>B, i am done with my work, and class B should not be extensible, then
 >>your proposal won't work.
 >>
 >
 >
 > Doesn't matter. Document that B isn't intended to be derived from.
 > You're done with your work.

Documentation is all very well and good; but compile-time error messages=20
when someone attempts to extend a class that's not meant to be extended=20
are better.

Not that I'm arguing for this particular feature; I'm agnostic about it.

I'm just pointing out that having the option to document a=20
characteristic is never a full substitute for having a language feature=20
which enforces that characteristic.

---
[ 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: francis.glassborow@ntlworld.com (Francis Glassborow)
Date: Wed, 4 Dec 2002 15:22:42 +0000 (UTC)
Raw View
In article <3DED8110.6FF05730@acm.org>, Pete Becker <petebecker@acm.org>
writes
>The distinction to keep in mind is that between "if you do this my code
>won't work" and "if you do this your code won't work." The former is why
>you make things private. The latter is not your responsibility.


I find that a false criterion. I do not make data private because my
code will not work otherwise but because I want various other benefits
such as the freedom to change my mind and the confidence that the
compiler knows all the ways in which that data can be accessed.

Freedom comes at a price, and half a century of computing demonstrates
that too much freedom is too expensive. Any time we use 'Do not do
that.' rather than 'You cannot do that.' we have a fracture point and we
have to consider the cost.


--
Francis Glassborow      ACCU
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---
[ 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: dnc@ccieurope.com (Dan Noedskouv Christensen)
Date: Wed, 4 Dec 2002 16:23:43 +0000 (UTC)
Raw View
Avi Kak wrote:

> The issue I am pursuing is whether C++ has an equivalent for the
> keyword "final" in Java that can be used to prevent a class from
> being extended and/or to prevent a base class function from being
> overridden in a derived class.

It hasn't.

I do think it would be useful to be able to specify that a class
cannot be derived from in C++.

The advantages I see:

1) Documentation. It tells that a class is a leaf in the inheritance
   chain.  A common design idiom is to only instantiate leaf classes,
   and such a functionality would support this idiom.

   It might even be possible for an implementation to combine this
   with a warning for instantiating non-final classes...

2) Optimization. It allows the compiler to resolve calls of virtual
   member functions at compile time, when the type is known to be a
   final class.

This also applies to the ability to "finalize" virtual functions but I
don't know if this is useful in praxis.

---
[ 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: petebecker@acm.org (Pete Becker)
Date: Wed, 4 Dec 2002 16:53:48 +0000 (UTC)
Raw View
"James Kuyper Jr." wrote:
>
> Pete Becker wrote:
>  > Doesn't matter. Document that B isn't intended to be derived from.
>  > You're done with your work.
>
> Documentation is all very well and good; but compile-time error messages
> when someone attempts to extend a class that's not meant to be extended
> are better.
>

Someone who derives from a class without reading the documentation is a
loose cannon. Compile-time error messages could prevent this derivation,
but don't address the underlying problem. Fix the real problem, not the
symptom.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: petebecker@acm.org (Pete Becker)
Date: Wed, 4 Dec 2002 16:55:05 +0000 (UTC)
Raw View
Francis Glassborow wrote:
>
> In article <3DED8110.6FF05730@acm.org>, Pete Becker <petebecker@acm.org>
> writes
> >The distinction to keep in mind is that between "if you do this my code
> >won't work" and "if you do this your code won't work." The former is why
> >you make things private. The latter is not your responsibility.
>
> I find that a false criterion. I do not make data private because my
> code will not work otherwise but because I want various other benefits
> such as the freedom to change my mind and the confidence that the
> compiler knows all the ways in which that data can be accessed.
>

You've completely misrepresented what I said. Please reread it, and keep
the context in mind.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.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://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Wed, 4 Dec 2002 18:55:31 +0000 (UTC)
Raw View
Dan Noedskouv Christensen wrote:
> 2) Optimization. It allows the compiler to resolve calls of virtual
>    member functions at compile time, when the type is known to be a
>    final class.

If this is really important, you can just write it this way:

struct Base
{
     virtual void foo();
};
struct Derived : Base
{
     void foo();
     void final_foo() { this->Derived::foo(); }
};

And of course this is only when you have a pointer or reference
to a Derived. If you have an actual Derived object, the compiler
doesn't need 'final' to avoid the virtual call.

Remember that C++, unlike Java, has non-virtual methods, and so
doesn't really need a keyword which says to cut off virtuality.

---
[ 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: Avi Kak <kak@purdue.edu>
Date: Fri, 22 Nov 2002 12:27:19 CST
Raw View
Hello:

  Is it safe to assume that the C++ standard is completely
  silent on the issue of blocking inheritance in class
  hierarchies?  I looked at Clause 10, but there is no
  mention of blocking inheritance (unless I overlooked
  its mention in the clause).

  The issue I am pursuing is whether C++ has an equivalent
  for the keyword "final" in Java that can be used to prevent
  a class from being extended and/or to prevent a base class
  function from being overridden in a derived class.

  I do realize that a class can be made non-extendible by
  placing its constructors in the private section of the class.
  But that obviously creates other complications if the class
  is meant for general-purpose use.

Avi Kak
kak@purdue.edu

---
[ 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: "bessermt" <bessermt@yahoo.com>
Date: Mon, 25 Nov 2002 12:09:54 CST
Raw View
Hi Avi,

No, there really is no Final keyword.  You can approximate it using a
variety of techniques but none are all the great.

Here's one:

class _NonDerivableHelper
{
protected:
    _NonDerivableHelper() {}
};

#define Final private virtual CTL::_NonDerivableHelper

Then try using it like so:

class YourClassName : public YourBaseClass, Final
{...};

I've had very limited success using this technique, but it might get you
started...

For more information on this issue see:

C/C++ User's Journal, May 2001 - by Shanker Chandrabose

Also check out:
comp.lang.c++.moderated newsgroup

"Avi Kak" <kak@purdue.edu> wrote in message
news:3DDE59BD.14E86075@purdue.edu...
>
> Hello:
>
>   Is it safe to assume that the C++ standard is completely
>   silent on the issue of blocking inheritance in class
>   hierarchies?  I looked at Clause 10, but there is no
>   mention of blocking inheritance (unless I overlooked
>   its mention in the clause).
>
>   The issue I am pursuing is whether C++ has an equivalent
>   for the keyword "final" in Java that can be used to prevent
>   a class from being extended and/or to prevent a base class
>   function from being overridden in a derived class.
>
>   I do realize that a class can be made non-extendible by
>   placing its constructors in the private section of the class.
>   But that obviously creates other complications if the class
>   is meant for general-purpose use.
>
> Avi Kak
> kak@purdue.edu
>
> ---
> [ 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                       ]
>
>

---
[ 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                       ]