Topic: non-virtual member functions considered harmful (Was: Proposal: Pointers 2)
Author: Michiel.Salters@cmg.nl (Michiel Salters)
Date: 1 Mar 2002 14:00:44 -0500 Raw View
John Nagle <nagle@animats.com> wrote in message news:<3C7AC5B4.8080208@animats.com>...
> I still contend that overriding non-virtual
> member functions should be detected as an error
> at compile-time.
Since I still have cases in which this is not an error,
I still contend this should not be an error.
( Old joke: Math prof presents proof of theorema to peers.
At the end, one attendant exclaims he's found a
counter example. Prof: "No problem, I've got another
proof" - from r.h.f )
> Ideally, the virtual/non virtual decision should be
> unnecessary. It's known by link time which functions
> actually need vtable machinery. But C++ is so
> locked into the dumb-linker model that it's
> hopeless to fix that.
I think we left we the dumb linker phase with "export".
Anyway, I think you've got a partial point here. I think
in the link phase you can determine for many methods
whether they need to be virtual or not, and the remainder
can safely be implemented as virtual. You might not be able
to determine with 100% certainty whether a method is
called virtually when the object pointer is obtained
through some opaque interface ( e.g. read from file )
Regards,
--
Michiel Salters
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: kanze@gabi-soft.de (James Kanze)
Date: 1 Mar 2002 14:01:10 -0500 Raw View
apm35@student.open.ac.uk (apm) wrote in message
news:<d1a33011.0202271352.2d1c6fed@posting.google.com>...
> pcm@cpugrid.net (P.M.) wrote in message
> > But what about Herb Sutter's NVI Idiom (Non Virtual Interface
> > Idiom)...
> > Public virtual functions directly and simultaneously specify both
> > the interface and the customizable behavior. This is a sign that
> > it is not separating concerns well.
> > #1 Prefer to make interfaces nonvirtual, using the Template Method.
> [snip]
> I am not sure about this at all. I see from GoF that the Template
> Method can be useful but I hesitate to make NVI a general rule. And
> what about pure interfaces, i.e a class that contains nothing but
> public pure virtuals ? NVI seems to be saying that interfaces are
> better if they are not virtual so how would you write a class that
> was just being used to specify interface (like Java interfaces) ?
There's a problem of nomenclature. The template pattern isn't the
only reason to make virtual functions non public, although Herb's
original article on the subject seemed to suggest this, and that the
template pattern be used universally. The name NVI describes the
technique, and not the pattern it is implementing, so it really
doesn't help either.
I use non-public virtual functions regularly to implement a
contractual interface -- if the interface defines a contract (and most
interfaces do), then it should not have any public virtual functions.
In this regard, we should perhaps differentiate the abstract concept
of interface (which is defined at the design level, and can be applied
in any programming language), and the Java keyword "interface", which
is used for a restricted form of inheritance (an implementation
detail). The abstract concept has several different interpretations;
the one I like best is from Bertrand Meyer, in which the interface
defines a contract. Of course, the Java "interface" cannot be used to
implement this form of interface -- the keyword is a misnommer.
Of course, there are interfaces which don't really have contracts --
anything used in what Kelvin Hennley called "call inversion", such as
most varieties of agent classes : callbacks, visitors, event handlers,
etc. If the role of the class is such that a formal contract doesn't
make sense, then there is no reason not to make the virtual functions
public. It would be a very rare application, however, in which such
classes were a majority, or even occured in important numbers.
Note that even here, there is a minimal contract, but the obligations
are all on the part of the calling party, and can normally be
expressed through the type system: EventHandler::handleEvent takes an
Event as parameter, for example, and not something else. In C++, you
can even state that the called function should not modify the object,
or that the "pointer" will never be null, via the type system.
--
James Kanze mailto:kanze@gabi-soft.de
Beratung in objektorientierer Datenverarbeitung --
-- Conseils en informatique orientie objet
Ziegelh|ttenweg 17a, 60598 Frankfurt, Germany, Til.: +49 (0)69 19 86 27
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: kenny_knecht@applied-maths.com (Kenny Knecht)
Date: 3 Mar 2002 09:33:46 -0500 Raw View
> I am not sure about this at all. I see from GoF that the Template
> Method can be useful but I hesitate to make NVI a general rule. And
> what about pure interfaces, i.e a class that contains nothing but
> public pure virtuals ? NVI seems to be saying that interfaces are
> better if they are not virtual so how would you write a class that was
> just being used to specify interface (like Java interfaces) ?
>
Well there's basically two interface you're talking about:
-the interface to the derived class ie the (pure) virtual functions
which are supposed to be protected
-the interface to the outside world, the public non-virtual functions
in the base class, which just forward to the virtual functions
The NVI-rule is all about seperating these two interfaces...
> The only reason I could come up with for using non-virtual member
> functions is to provide clean or guarded access to private data members.
ok, but that reason applies in 95% of all cases.
Another reason could be to conceptually put all the info about a
"thing" together??? Classes are the stronger version of a namespace to
me much more than they are the fancy wrapper for a vtable, as you seem
to imply.
kk
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: pcm@cpugrid.net (P.M.)
Date: 24 Feb 2002 09:27:28 -0500 Raw View
Thant Tessman <thant@acm.org> wrote in message news:<3C681444.8000001@acm.org>...
[SNIP]
> ... it's that if
> there's no reason for a member function to be virtual, there's probably
> no reason it should be a member function.
But what about Herb Sutter's NVI Idiom (Non Virtual Interface
Idiom)...
>From C/C++ Users Journal., Sept 2001, p53:
Public virtual functions directly and simultaneously specify both the
interface and the customizable behavior. This is a sign that it is
not separating concerns well.
#1 Prefer to make interfaces nonvirtual, using the Template Method.
#2 Prefer to make virtual functions private.
#3 Only if derived classes need to invoke the base implementation of a
virtual function, make the virtual function protected.
For the special case of the destructor only:
#4 A base class destructor should be either public and virtual, or
protected and nonvirtual (only if it is not a concrete class and is
intended to be used as a base class).
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: John Nagle <nagle@animats.com>
Date: 27 Feb 02 03:52:30 GMT Raw View
I still contend that overriding non-virtual
member functions should be detected as an error
at compile-time.
Ideally, the virtual/non virtual decision should be
unnecessary. It's known by link time which functions
actually need vtable machinery. But C++ is so
locked into the dumb-linker model that it's
hopeless to fix that.
John Nagle
Animats
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: apm35@student.open.ac.uk (apm)
Date: 01 Mar 02 07:18:59 GMT Raw View
pcm@cpugrid.net (P.M.) wrote in message
> But what about Herb Sutter's NVI Idiom (Non Virtual Interface
> Idiom)...
> Public virtual functions directly and simultaneously specify both the
> interface and the customizable behavior. This is a sign that it is
> not separating concerns well.
>
> #1 Prefer to make interfaces nonvirtual, using the Template Method.
[snip]
I am not sure about this at all. I see from GoF that the Template
Method can be useful but I hesitate to make NVI a general rule. And
what about pure interfaces, i.e a class that contains nothing but
public pure virtuals ? NVI seems to be saying that interfaces are
better if they are not virtual so how would you write a class that was
just being used to specify interface (like Java interfaces) ?
Regards,
apm
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: "Cyrille Chipilov" <cyrille@softek.fr>
Date: 1 Mar 2002 10:40:27 -0500 Raw View
> I am not sure about this at all. I see from GoF that the Template
> Method can be useful but I hesitate to make NVI a general rule. And
> what about pure interfaces, i.e a class that contains nothing but
> public pure virtuals ? NVI seems to be saying that interfaces are
> better if they are not virtual so how would you write a class that was
> just being used to specify interface (like Java interfaces) ?
Well, the point behind NVI is that there are actually two interfaces in an
interface: interface towards users, and interface towards implementors. So,
a pure virtual class (interface in Java parlance) talks to two kind of
developers: those who use objects which implements the interface, and those
who implements those objects.
NVI is about decoupling the concerns; after all, it may happen during a
refactoring that you need to change the interface towards implementors, or
the interface towards users. In the process, you might have to change the
1-1 mapping between inline template methods and virtual methods.
If you are 100% sure you want to keep the Java interface semantics, and
you're willing to tie the specialisation and usage interfaces, then NVI is
not needed. OTOH, if you don't mind your "interface classes" gaining some
flesh because at some point in the project, it makes sense to do so, then
C++/NVI can be quite useful.
-- Cyrille
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: "Marco Dalla Gasperina" <marcodg@attbi.com>
Date: 13 Feb 2002 11:07:13 -0500 Raw View
"Thant Tessman" <thant@acm.org> wrote in message
news:3C681444.8000001@acm.org...
>
> The only reason I could come up with for using non-virtual member
> functions is to provide clean or guarded access to private data members.
> This is a reason you brought up yourself.
And this is easily achieved with 'friend' is it not?
marco
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: Thant Tessman <thant@acm.org>
Date: 14 Feb 02 05:34:27 GMT Raw View
Marco Dalla Gasperina wrote:
> "Thant Tessman" <thant@acm.org> wrote in message
> news:3C681444.8000001@acm.org...
>
>>The only reason I could come up with for using non-virtual member
>>functions is to provide clean or guarded access to private data members.
>>This is a reason you brought up yourself.
>>
>
> And this is easily achieved with 'friend' is it not?
Yes, except in the case of conversion operators. (But this might be
reason to reconsider other aspects of the language design...)
-thant
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: Michiel.Salters@cmg.nl (Michiel Salters)
Date: 14 Feb 2002 06:33:41 -0500 Raw View
Thant Tessman <thant@acm.org> wrote in message news:<3C681444.8000001@acm.org>...
> Terje Slettebx wrote:
>
> [...]
>
>
> > "Andrei Alexandrescu" <andrewalex@hotmail.com> wrote in message
> > news:<a3tf4g$1atquh$1@ID-14036.news.dfncis.de>...
> >
> >
> >>Basically my belief is that nonvirtual member functions in general are
> >>an unnecessary cutesy in C++ that wahses people's brains, leads to bad
> >>programs, and will take many years to wear off. For smart pointers in
> >>particular, they can do even more harm.
> >>
> >
> > Huh? Are you saying that all member functions (in general) should be
> > virtual?
>
> I giggled when I read Andrei make that statement. First, because I
> happen to strongly agree with him on this point, and second, because I
> knew that it would push somebody's button.
>
> It's not that all member functions should be virtual, it's that if
> there's no reason for a member function to be virtual, there's probably
> no reason it should be a member function.
>
> The member function calling syntax is a good thing when a member
> function is virtual because it distinguishes the object whose runtime
> type will determine which function gets called. But if the member
> function isn't virtual, then the member function calling syntax is
> purely syntactic sugar.
[SNIP]
> The only reason I could come up with for using non-virtual member
> functions is to provide clean or guarded access to private data members.
> This is a reason you brought up yourself.
>
> [...]
That's one reason. Number two is of course because the standard requires
something to be a non-virtual member function - e.g. constructors - and
number three is that library base classes might want/need to provide
private functions to their derived classes; non-member functions lack
protection.
I don't think this is a complete list, either.
Regards,
--
Michiel Salters
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: Thant Tessman <thant@acm.org>
Date: 13 Feb 02 01:20:45 GMT Raw View
Terje Sletteb wrote:
[...]
> "Andrei Alexandrescu" <andrewalex@hotmail.com> wrote in message
> news:<a3tf4g$1atquh$1@ID-14036.news.dfncis.de>...
>
>
>>Basically my belief is that nonvirtual member functions in general are
>>an unnecessary cutesy in C++ that wahses people's brains, leads to bad
>>programs, and will take many years to wear off. For smart pointers in
>>particular, they can do even more harm.
>>
>
> Huh? Are you saying that all member functions (in general) should be
> virtual?
I giggled when I read Andrei make that statement. First, because I
happen to strongly agree with him on this point, and second, because I
knew that it would push somebody's button.
It's not that all member functions should be virtual, it's that if
there's no reason for a member function to be virtual, there's probably
no reason it should be a member function.
The member function calling syntax is a good thing when a member
function is virtual because it distinguishes the object whose runtime
type will determine which function gets called. But if the member
function isn't virtual, then the member function calling syntax is
purely syntactic sugar. And this particular syntactic sugar is bad for
at least two reasons that I can think of.
First, it encourages an object/message design where none may be
appropriate. For example, I have a collection of classes for doing 3D
math. It includes "transformer" classes like matrix, quaternion, scale,
translate, etc. It also includes "transformee" classes like point,
vector, plane, etc. For efficiency, there is a separately implemented
transform function for every transformer/transformee pair. Originally I
implemented "transform" as a member function of each individual
transformer class. (I did it out of pure habit. Andrei is right about
this particular bad habit taking many years to wear off.) The problem is
that with this arrangement, every time you introduce a new transformee,
you need to go touch all the effected transformers. Bad decoupling. Bad
design.
The second reason is that template metaprogramming (of which Andrei is a
master) is made easier when your syntax is consistent. In fact, I've
more than once found the need to write a global function that does
nothing but turn around and call a virtual member function just to make
template programming cleaner.
The only reason I could come up with for using non-virtual member
functions is to provide clean or guarded access to private data members.
This is a reason you brought up yourself.
[...]
-thant
[ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: 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.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]