[comp.lang.c++] fixing pitfall in virtual members

dove@rocket.stars.flab.Fujitsu.JUNET (Webster Dove) (02/14/89)

I have recently had two staff waste a day each chasing very similar
problems with virtual members.  I believe a minor change to the
language definition could eliminate a significant pitfall that now
exists.

Both people were working on Interviews applications.  Mike was trying
to upgrade an old application to a new Interviews rev.  Kevin was
writing a new application.  Part of the both applications required
that the programmer create a virtual function member in a class they
wrote that would catch an event (exposure I believe).  Unfortunately,
in Mike's case, the syntax of the call had changed between revs and in
Kevin's case, the documented syntax was wrong.

The result was that the function members they had declared were
considered new members (as opposed to shadowing virtuals from the base
class) and were never called because their syntax was not the required
one.  Since C++ requires that the base class provide a default member,
the package has one which does nothing.  Therefore, the programs
compiled without any warnings.  However, when they were run the
results were very obscure behaviors that took considerable skill and
effort to diagnose.

My recommendation is the following: eliminate the requirement to
restate the syntax of virtual functions in the derived class
declaration.  If they must be restated, require the keyword "shadow"
in front to explicitly connote that the declaration must "hook up"
with an identical virtual declaration in the base class.  This would
have given my two staff obvious syntax errors to correct and reduced
the expended time by orders of magnitude.

I must emphasize that these were both competent people who
independently ran into the same problem.  It suggests to me a
substantial risk in using the language.
--
		Dr. Webster Dove
		Computing Systems and Architectures
		Advanced Signal Processing Engineering (ASPEN) Dept.
		Sanders Associates (a Lockheed Company)

ark@alice.UUCP (Andrew Koenig) (02/15/89)

In article <DOVE.89Feb14122134@rocket.stars.flab.Fujitsu.JUNET>, dove@rocket.stars.flab.Fujitsu.JUNET (Webster Dove) writes:

> My recommendation is the following: eliminate the requirement to
> restate the syntax of virtual functions in the derived class
> declaration.  If they must be restated, require the keyword "shadow"
> in front to explicitly connote that the declaration must "hook up"
> with an identical virtual declaration in the base class.  This would
> have given my two staff obvious syntax errors to correct and reduced
> the expended time by orders of magnitude.

Here's a much easier solution:

Issue a warning when a non-virtual function declaration
hides a virtual function with the same name declared in
a base class.

Adding a new keyword is not a minor change.
-- 
				--Andrew Koenig
				  ark@europa.att.com

joemac@Apple.COM (Joe MacDougald) (02/16/89)

There has been a proposal here at Apple to extend the language to cover
this unsafe situation.  The keyword suggested to be required when a virtual
function was specialized in a derived class is "overload".  This keyword 
is required in Object Pascal in the analogous situation.  For portability
one could simply "#define overload virtual".

This was suggested to Bjarne but alas the language is too mature for such an 
addition.


|	UUCP		...!{decwrl, inhp4, hplabs, sun}!apple!joemac          |
|	Domain		joemac@apple.com				       |
|	AppleLink	MACDOUGALD1					       |
|							"be the ball ..."      |

johnson@p.cs.uiuc.edu (02/18/89)

Webster Dove described the problem that can occur when the implementer
of a derived class declares a virtual member function with the wrong
name.  Briefly, the compiler does not issue any warnings but uses
the function inherited from the base class, and the new function never
gets called.

One way to minimize this problem is to make base classes abstract
(i.e. their virtual functions are only place-holders) and to make
the virtual functions give error messages if they are ever called.
This technique has worked well for us.

Ralph Johnson

rfg@riunite.ACA.MCC.COM (Ron Guilmette) (02/19/89)

In article <DOVE.89Feb14122134@rocket.stars.flab.Fujitsu.JUNET> dove@rocket.stars.flab.Fujitsu.JUNET (Webster Dove) writes:
>I have recently had two staff waste a day each chasing very similar
>problems with virtual members.

<<... a sad story ensues ... >>

>...Since C++ requires that the base class provide a default [virtual] member,
>the package has one which does *nothing*.  Therefore, the programs
>compiled without any warnings.  However, when they were run the
>results were very obscure behaviors that took considerable skill and
>effort to diagnose.

Please correct me if I am wrong, but couldn't you have avoided your
trouble if you had defined the "default" virtual member function
in the base class to do something which would let you know that
it had been called by mistake, e.g. calling abort() or something?

That is what I do when I have virtual member function declared in
a base class which are just there as "placeholders" are which are
not supposed to  be called in practice.


-- 
// Ron Guilmette  -  MCC  -  Experimental (parallel) Systems Kit Project
// 3500 West Balcones Center Drive,  Austin, TX  78759  -  (512)338-3740
// ARPA: rfg@mcc.com
// UUCP: {rutgers,uunet,gatech,ames,pyramid}!cs.utexas.edu!pp!rfg

dove@rocket.stars.flab.Fujitsu.JUNET (Webster Dove) (02/23/89)

In article <91@riunite.ACA.MCC.COM> rfg@riunite.ACA.MCC.COM (Ron Guilmette) writes:

   Please correct me if I am wrong, but couldn't you have avoided your
   trouble if you had defined the "default" virtual member function in
   the base class to do something which would let you know that it had
   been called by mistake, e.g. calling abort() or something?

Yes.  Exactly my advice when we write the base class (also recommended
by johnson@p.cs.uiuc.edu).  However, in this case, the base was
written by Mark Linton and at least at the time he did not recognize
the risk.

   That is what I do when I have virtual member function declared in a
   base class which are just there as "placeholders" are which are not
   supposed to be called in practice.

That will detect at run time a failure to overload the base virtual
definition.   I guess barring a change to the language, I would prefer
a compiler warning of the form recommended by Andrew Koenig:

   Issue a warning when a non-virtual function declaration
   hides a virtual function with the same name declared in
   a base class.

This would detect the problem at compile time, and could be added to a
compiler as a switch (as the -fsingle switch was added to correct the
single to double conversion misfeature in C).
--
		Dr. Webster Dove
		Computing Systems and Architectures
		Advanced Signal Processing Engineering (ASPEN) Dept.
		Sanders Associates (a Lockheed Company)

mikem@otc.otca.oz (Mike Mowbray) (02/26/89)

    ** Ron Guilmette suggested that the trouble could be avoided by having
       the base class version of the virtual function do something like abort().

    **  Webster Dove supported this, indicating that this was his standard
	advice when writing a base class.

If the inheritance depth were greater than 1, this scheme wouldn't make sense.


		Mike Mowbray	    ACSnet: mikem@otc.oz
		Network R&D	    UUCP:   {uunet,mcvax}!otc.oz!mikem
		|||| OTC ||	    Phone:  (02) 287-4104
				    Snail:  GPO Box 7000, Sydney, Australia