Topic: Dynamic type loss considered harmless


Author: craig@gpu.utcs.utoronto.ca (Craig Hubley)
Date: 3 Mar 91 00:55:15 GMT
Raw View
In article <27CD13B1.649B@tct.uucp> chip@tct.uucp (Chip Salzenberg) writes:
>Adding dynamic type information would entail significant changes to
>the meaning of "type".  Under current rules, a |Base| that is part of
>a |Derived| is indistinguishable from a plain |Base|.  Inventing a
>distinction between them would require rethinking the type conversion
>rules, especially in view of multiple inheritance.

You refer only to the byte storage that is associated with the type Base.

In behavior terms, the distinction is already there.  I can build a Derived
that acts very similarly, or totally differently from its Base, through
private inheritance, hiding members, or other means.  With virtual inheritance,
I can decide that several functions may share one copy of the Base part of
the object.

The distinction only matters if one is going to invoke type-specific behavior
in an application-specific context.  The type tag is necessary for those
cases.

>attitude that the feature is almost indepensible.  IMHO, it's not.

Every other object-oriented language has it, so burden of proof is on you.

>>Those other uses can be supported without requiring every object to carry
>>a type tag through to runtime.
>
>I don't see how, unless you are referring to the optimization that
>objects without virtual function tables do not maintain a type tag.

I do.  And objects that don't have virtual functions don't have any
potentially type-specific functionality.  So NO additional type tags
are required - we only want to see what's already there.

>>As it stands, you cannot add any type- and context-specific functionality
>>to an object without access to its source code.  This greatly restricts
>>reusability, to a level between that of say, Eiffel, and that of Ada.
>
>"Well, don't do that, then."  If I can't modify the source code to a
>class, I may use use it, but I usually won't derive from it.

Then you will never extend anyone else's code, use a framework, etc.  It
seems we have found the source of our disagreement.

You want a "better C".  We want a "reusable library language".  I would
suggest that if we can get what we want without imposing any overhead on
you (in fact removing some), you should stop arguing with us.  :)

>>I do not consider this sufficient to support a components industry, as it
>>leaves too many ways for producing programmers to cut off options for those
>>building on their code.
>
>IMHO, any attempt to distribute binary-only C++ components intended
>for use _as_base_classes_ is probably doomed to failure in all but the

If true, I would suggest that C++ itself is probably doomed to failure too.
No need to argue this point, we have been over it already.

>simplest cases, for reasons that go far beyond the lack of dynamic
>typing.  Adding a type tag won't solve the problems of non-virtual
>member functions and private (as opposed to protected) members.

Why are private members a problem ?  The guarantee a programmer makes in
providing public members are that they are sufficient to do whatever the
object is supposed to do - access to privates is in principle unnecessary.
If this is untrue in some cases, then the member should be protected or
(more likely) the functionality redefined.

>So C++ isn't a good language for binary components; so what?  If I
>want Objective-C, I know where to find it.

As I say, we've been over this already.  Objective-C has its own problems.

I would think you are in a minority in not wanting C++ to support binary
components.  I would appreciate hearing from others on this point.  On
this question I think we must agree to disagree.
--
  Craig Hubley   "...get rid of a man as soon as he thinks himself an expert."
  Craig Hubley & Associates------------------------------------Henry Ford Sr.
  craig@gpu.utcs.Utoronto.CA   UUNET!utai!utgpu!craig   craig@utorgpu.BITNET
  craig@gpu.utcs.toronto.EDU   {allegra,bnr-vpa,decvax}!utcsri!utgpu!craig




Author: chip@tct.uucp (Chip Salzenberg)
Date: 4 Mar 91 16:30:23 GMT
Raw View
According to craig@gpu.utcs.utoronto.ca (Craig Hubley):
>In article <27CD13B1.649B@tct.uucp> chip@tct.uucp (Chip Salzenberg) writes:
>>Adding dynamic type information would entail significant changes to
>>the meaning of "type".  Under current rules, a |Base| that is part of
>>a |Derived| is indistinguishable from a plain |Base|.
>
>In behavior terms, the distinction is already there.

I stand corrected.

>>attitude that the feature is almost indepensible.  IMHO, it's not.
>
>Every other object-oriented language has it, so burden of proof is on you.

Ha!  My statement is, "ClassID is not necessary _for_C++_."  That
languages X, Y and Z have it is irrelevant.  They aren't C++.

>>>As it stands, you cannot add any type- and context-specific functionality
>>>to an object without access to its source code.  This greatly restricts
>>>reusability, to a level between that of say, Eiffel, and that of Ada.
>>
>>"Well, don't do that, then."  If I can't modify the source code to a
>>class, I may use use it, but I usually won't derive from it.
>
>Then you will never extend anyone else's code, use a framework, etc.

I will extend someone else's code -- _if_ I have source, and if I have
permission to change it as necessary.  In my estimation, attempts to
extend C++ code without the authority to make changes -- especially if
such extensions depend on what_type_are_you() tests -- will result in
"an ill-assorted collection of poorly matching parts, forming a
distressing whole": a kludge.

>It seems we have found the source of our disagreement.

Perhaps we have.

>You want a "better C".  We want a "reusable library language".

Given that we are using C++, we _all_ -- yes, you too -- want a
"better C".  The question is, which improvements are good and which
aren't.  I think ClassID is marginal at best.

>I suggest that if we can get what we want without imposing any overhead on
>you (in fact removing some), you should stop arguing with us.  :)

The language feature has merit, as I mentioned before, and I don't
oppose its introduction pe se.  My objection is not to the feature,
but to the undeserved praises being heaped upon it, and to the bad
code that could result from its unrestrained use.

>>IMHO, any attempt to distribute binary-only C++ components intended
>>for use _as_base_classes_ is probably doomed to failure ...
>
>If true, I would suggest that C++ itself is probably doomed to failure
>too.

"I don't know what language we'll be using in ten years, but it will
be called C++."  You should know by now that technical issues have
seldom stopped languages from becoming mind-numbingly popular.  C++
has too much momentum to be stopped now.

>>Adding a type tag won't solve the problems of non-virtual
>>member functions and private (as opposed to protected) members.
>
>Why are private members a problem ?

They are a problem in the same way that non-virtual member functions
are a problem: they are opportunities for the class creator to guess
wrong about future re-use patterns.  Neither good nor bad programmers
can see the future.  "Give me source code or give me a pink slip."

>I would think you are in a minority in not wanting C++ to support binary
>components.

It's not that I don't _want_ C++ to support binary components.  I do.
I also want it to eliminate hunger.  I don't believe it can do either.
--
Chip Salzenberg at Teltronics/TCT     <chip@tct.uucp>, <uunet!pdn!tct!chip>
   "All this is conjecture of course, since I *only* post in the nude.
    Nothing comes between me and my t.b.  Nothing."   -- Bill Coderre




Author: thomasw@hpcupt1.cup.hp.com (Thomas Wang)
Date: 6 Mar 91 02:13:33 GMT
Raw View
/ hpcupt1:comp.std.c++ / chip@tct.uucp (Chip Salzenberg) /  8:30 am  Mar  4, 1991 /

It is possible to abuse the type tag feature.  But let me describe to you a
situation typing information is required.

Suppose we have an 'array' library that always operates on objects of
class 'object'.  Now suppose you have a class called 'person'.  You
put some 'person' objects into an array variable.  A problem that will
come up when one tries to retrive the objects out of the array.
A 'person*' that was put into the array will come out as 'object*'.
Is it safe to cast from 'object*' to 'person*'?  Conceptually speaking,
it is safe to do the casting iff the object isa 'person*'. (note 1)
This question cannot be answered without knowing some run-time typing
information.  Assuming you can do the cast, then you can call member
functions of 'person', such as ((person*) obj)->walk().

The designer of the 'object' class have no way to know there will be a 'person'
class later, so defining walk() function as base virtual from the 'object'
class is really not a solution.

So far, the only good use of type information I have found is the example
above.  Seems in all other cases, virtual functions can serve better than
explicitly looking at runtime typing information.

(note 1)
C++ multiple inheritance violates this assumption, but that's another
story...


 -Thomas Wang
              (Everything is an object.)
                                                     wang@hpdmsjlm.cup.hp.com
                                                     thomasw@hpcupt1.cup.hp.com




Author: daves@ex.heurikon.com (Dave Scidmore)
Date: 7 Mar 91 07:39:42 GMT
Raw View
(Thomas Wang) writes:

>Suppose we have an 'array' library that always operates on objects of
>class 'object'.  Now suppose you have a class called 'person'.  You
>put some 'person' objects into an array variable.  A problem that will
>come up when one tries to retrive the objects out of the array.
>A 'person*' that was put into the array will come out as 'object*'.
>Is it safe to cast from 'object*' to 'person*'?  Conceptually speaking,
>it is safe to do the casting iff the object isa 'person*'. (note 1)
>This question cannot be answered without knowing some run-time typing
>information.  Assuming you can do the cast, then you can call member
>functions of 'person', such as ((person*) obj)->walk().

This may be a silly question but since storing a pointer to an object can
lead to that object changing after being installed in an array, would it
not be better to actually store the object. Making a generic array class
which is pointer based is an object abuse waiting to happen. For example
I might declare a single 'person' object iteratively fill it from some
database, installing each copy in the array. I would expect that I was making
an array of objects and not an array pointers, so I would expect an array
of unique object, but get an array where only one object is referenced.

My point is that in terms of the design of a "generic" array class the
pointer implementation makes it too easy for someone else using the class
to use it wrongly. Templates seem like the ideal solution when you have an
array of class objects.

>The designer of the 'object' class have no way to know there will be a 'person'
>class later, so defining walk() function as base virtual from the 'object'
>class is really not a solution.

>So far, the only good use of type information I have found is the example
>above.  Seems in all other cases, virtual functions can serve better than
>explicitly looking at runtime typing information.

It seems to me that situations where you need to know type information at
run time are the exception and not the norm. That being the case would it
not make more sense to only encode type information when you may need to
know an objects type and do this by making a class that has type information
and a union of all possible object types? In any event it seems to me that
some special case handling of the need for dynamic type information can be
when needed as the need does not arise frequently and workaraounds are usualy
available to the enterprising programmer. In other words when I find an
detail of a programs structure gets sticky, I usualy find another way to
structure the program, preferable one that is less sticky.
--
Dave Scidmore, Heurikon Corp.
dave.scidmore@heurikon.com




Author: chip@tct.uucp (Chip Salzenberg)
Date: 7 Mar 91 16:06:40 GMT
Raw View
According to thomasw@hpcupt1.cup.hp.com (Thomas Wang):
>Suppose we have an 'array' library that always operates on objects of
>class 'object'.  Now suppose you have a class called 'person'.  ...
>A 'person*' that was put into the array will come out as 'object*'.

Such an |array| class is badly designed, because it depends on all
objects being derived from |object|, which is an invalid assumption
for the C++ language.

In C++ 2.1, I would make |array| a template, so that the writer of
|array| would not depend on a specific base class like |object|.
Unfortunately, templates are not widely available yet.

Therefore, I use the preprocessor to make type-specific vector classes
from a generic type-ignorant |Vector| class.  I use the same approach
for linked lists.  These classes work: I use them in production code.

I know that heavy use of the preprocessor is a hack.  But, with
apologies to Winston Churchill: `Using the preprocessor for collection
classes is the worst solution imaginable, except for all the others.'
Preprocessor-based collections preserve static type information to
whatever degree is desired by the consumer, which makes them cleaner
than any type-tag solution.  And the preprocessor can be ditched later
when templates arrive, without any loss of type safety.
--
Chip Salzenberg at Teltronics/TCT     <chip@tct.uucp>, <uunet!pdn!tct!chip>
   "All this is conjecture of course, since I *only* post in the nude.
    Nothing comes between me and my t.b.  Nothing."   -- Bill Coderre




Author: chip@tct.uucp (Chip Salzenberg)
Date: 28 Feb 91 14:29:04 GMT
Raw View
>>>There is no "cast to the dynamic type" operator ...
>>
>>That's a necessary result of the most basic type rules.
>
>Then why are Bjarne/Andy in favor of it ?  At least so I've heard...

I overstated my case.  Let me try again:

Adding dynamic type information would entail significant changes to
the meaning of "type".  Under current rules, a |Base| that is part of
a |Derived| is indistinguishable from a plain |Base|.  Inventing a
distinction between them would require rethinking the type conversion
rules, especially in view of multiple inheritance.

>Dynamic type loss is OK if the type is not useful at runtime.  However,
>it can be useful in many more ways than deciding which version of its
>predefined (and often unchangeable) functions to call at runtime.

Granted, it can be useful, in the same sense that "goto" can be
useful.  As I've mentioned in another article, I've decided that I
object, not so much to the proposed feature, but to the apparent
attitude that the feature is almost indepensible.  IMHO, it's not.

>Those other uses can be supported without requiring every object to carry
>a type tag through to runtime.

I don't see how, unless you are referring to the optimization that
objects without virtual function tables do not maintain a type tag.

>As it stands, you cannot add any type- and context-specific functionality
>to an object without access to its source code.  This greatly restricts
>reusability, to a level between that of say, Eiffel, and that of Ada.

"Well, don't do that, then."  If I can't modify the source code to a
class, I may use use it, but I usually won't derive from it.

>I do not consider this sufficient to support a components industry, as it
>leaves too many ways for producing programmers to cut off options for those
>building on their code.

IMHO, any attempt to distribute binary-only C++ components intended
for use _as_base_classes_ is probably doomed to failure in all but the
simplest cases, for reasons that go far beyond the lack of dynamic
typing.  Adding a type tag won't solve the problems of non-virtual
member functions and private (as opposed to protected) members.

So C++ isn't a good language for binary components; so what?  If I
want Objective-C, I know where to find it.
--
Chip Salzenberg at Teltronics/TCT      <chip@tct.uucp>, <uunet!pdn!tct!chip>
"It's not a security hole, it's a SECURITY ABYSS." -- Christoph Splittgerber
   (with reference to the upage bug in Interactive UNIX and Everex ESIX)