[comp.lang.c++] Will C++ 2.1 fix the virtual function linkage problem?

dove@batman.uucp (Webster &) (06/02/90)

The problem:

Suppose a user of a library (e.g. InterViews) has set up many virtual
member functions for derived classes that inherit class declarations
from the library.  Assume that these member functions are being
invoked somewhere inside the library that the user is aware of in
general, but not in detail.  Now assume that a new release of the
library comes out and the details of the calling syntax for some of
these virtual functions is superficially changed, and the user has not
read all the new documentation carefully or the documentation fails to
mention the change.

This causes the derived class virtual functions to "fail to link" with
the base class declarations leading to program failure.  There is no
compile time warning since the derived virtual declarations are now
treated as new function members starting at the derived class level.

I have had this happen several times on programs I controlled.  I see
this as a severe risk.  Is this being fixed?

I have previously (5/12/87) discussed this issue and I gather it has
come up as a recurring theme.  I think I have a fix.  Since I have not
been reading this list for a while, forgive me if it has been
discussed.

Suppose you allow the derived class to inherit the declaration of the
virtual member.  

class base_class {
public: 
	virtual base_virtual();
};

int base_class::base_virtual() { ... default behavior ... }

class derived_class : public base_class {
}

int derived_class::base_virtual() { ... derived behavior ... }


This would be back compatible with existing code, not require any new
keywords, and allow me to fix my problem with a library line
InterViews without requiring any changes to the library.  This allows
me to explicitly state (by ommision) that I am expecting there to be a
matching inherited virtual and would yield a compile time error if
that linkage failed.

Comments?

Web
--
Dr. Webster Dove				Dr. Webster Dove
Experimental Computing Systems ('X')		Lockheed Sanders Inc.  
Signal Processing Center of Technology		144 Daniel Webster Hwy.
Lockheed Sanders Inc.				Merrimack, NH.  03054  
						
email: 
		.!uunet!rocket!dove
	(or )	@uunet.uu.net:dove@rocket.uucp

jef@well.sf.ca.us (Jef Poskanzer) (06/03/90)

In the referenced message, dove@batman.uucp (Webster &) wrote:
>Suppose you allow the derived class to inherit the declaration of the
>virtual member.  
>
>class base_class {
>public: 
>	virtual base_virtual();
>};
>
>int base_class::base_virtual() { ... default behavior ... }
>
>class derived_class : public base_class {
>}
>
>int derived_class::base_virtual() { ... derived behavior ... }
>
>This would be back compatible with existing code, not require any new
>keywords, and allow me to fix my problem with a library line
>InterViews without requiring any changes to the library.  This allows
>me to explicitly state (by ommision) that I am expecting there to be a
>matching inherited virtual and would yield a compile time error if
>that linkage failed.

I agree that this is a big problem with C++, but your proposed solution
seems weird.  Explicitly state by omission?  What does the derived class
do if it doesn't want to re-define the function?  Or if it wants to
define a totally different function that happens to have the same name?

How about if the derived class can declare that it will be re-defining a
virtual function without having to re-state the type and arguments of
the function?  Like this:

class derived_class : public base_class {
	base_virtual;
}

Hmm, except this doesn't work either if the base class defines more
than one virtual function with that name, but with different arguments.

I dunno, I just started on C++ a few weeks ago, and already I love/hate
it.
---
Jef

  Jef Poskanzer  jef@well.sf.ca.us  {ucbvax, apple, hplabs}!well!jef
             "She's not a woman -- she's the Terminator!"

roger@procase.UUCP (Roger H. Scott) (06/03/90)

In article <DOVE.90Jun2102921@batman.uucp> dove@batman.uucp (Webster &) writes:
>The problem: (paraphrased somewat -rhs)
>
>Suppose a user of a library (e.g. InterViews) has redefined many virtual
>functions from the library.  Now assume that a new release of the
>library comes out and the type signature for some of these functions is changed,
> and the user is not fully aware of the change.
>
>This causes the derived class virtual functions to "fail to link" with
>the base class declarations leading to program failure.  There is no
>compile time warning since the derived virtual declarations are now
>treated as new function members starting at the derived class level.

1. This is not a language definition issue, requiring a language change.  It
is a compiler design issue, requiring a compiler change.
2. The relevant change has been made in the AT&T's 2.0 cfront compiler.  In
the case you describe you would get a warning that the base class's virtual
function(s) have been hidden by the functions in the derived class.  Remember
that overloading only occurs within a single scope, and the members of a derived
class are considered to be in a different scope than the members of a base class.

>...
>Suppose you allow the derived class to inherit the declaration of the
>virtual member.  
Think about overloading and you will see that things are not nearly as neat
and simple as you describe them.
@
@
@
@
@
@
@
@
@

jamiller@hpcupt1.HP.COM (Jim Miller) (06/07/90)

>I agree that this is a big problem with C++, but your proposed solution
>seems weird.  Explicitly state by omission?  What does the derived class
>do if it doesn't want to re-define the function?  Or if it wants to
>define a totally different function that happens to have the same name?
>
>How about if the derived class can declare that it will be re-defining a
>virtual function without having to re-state the type and arguments of
>the function?  Like this:
>
>class derived_class : public base_class {
>	base_virtual;
>}
>
>  Jef Poskanzer  jef@well.sf.ca.us  {ucbvax, apple, hplabs}!well!jef
>             "She's not a woman -- she's the Terminator!"
>

As noted, overloading would give problems if you do not give the type of
arguments.  It seems to me that I want to redefine a routine I should give
the same parameters, but the compiler should help me make sure that the
base virtual function has not changed it's parameters.  

I want to introduce a new keyword (oh, no, not another!): "virtual+".
Virtual+ says that it is replacing a virtual function from an inherited
class.  If there is no match, the compiler gives and error.

"virtual-" might be also introduced, meaning this function is NOT supposed
to replace a base function (at least it didn't when I wrote it...).


class base_class {
public:
        virtual base_virtual();
};

int base_class::base_virtual() { ... default behavior ... }


class derived_class : public base_class {
        virtual+  base_virtual();  // name and parms must match exactly!
               ^****
}

int derived_class::base_virtual() { ... derived behavior ... }


I think this would solve the "but the library changed and never told me"
problem.  It should be completely compatible with existing code.

I would think that I would have to know EXACTLY the parameters of the
routine I'm trying to replace in my new function.  Yes, there would
be still gotcha's.  If you are counting on type conversion, then the base
class includes a new function by the same name that now has the right
types.  In that case your derived function would not get called
after type conversion, the new function would get called without any
type conversion.  However, by doing explicit type conversion you could
write your code so that it would call the correct routine no matter
what the base class did.  

This mechanism would allow one to program more defensively than is
now possible.

      jim - $.02 - miller

   These opinions are not necessarily those of the company I work for.