Topic: Inheritance and references to pointers
Author: ark@research.att.com (Andrew Koenig)
Date: 1995/09/26 Raw View
In article <445k3k$18p@isoit109.bbn.hp.com> Jean-Rene Bouvier <jr@isoit109.bbn.hp.com> writes:
> 2. what is the reason for this restriction, or rather, is there any reason to
> keep this restriction (apart from the fact that a DerviedObject*& bears no
> inheritance relationship to an Object*&) ?
The real problem is that a DerivedObject* might not have the same
internal representation (i.e. bit pattern) as an Object*, because
there is no reason to believe that the Object part of a DerivedObject
is at the beginning of the DerivedObject. In the presence of multiple
inheritance, we can guarantee that a DerivedObject* will have a
different representation from a pointer to at least one of its
base classes.
--
--Andrew Koenig
ark@research.att.com
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: fenster@cs.columbia.edu (Sam Fenster)
Date: 1995/09/27 Raw View
> Jean-Rene Bouvier <jr@isoit109.bbn.hp.com> writes:
>> 1. is my understanding correct (i.e. that a DerviedObject*& cannot be
>> passed in lieu of an Object*&) ?
martelli@cadlab.cadlab.it (Alex Martelli) writes:
> It would violate type-safety. It may be easier to see with pointers to
> pointers:
> B b;
> void tricky(B ** pointer_to_pointer)
> {*pointer_to_pointer = &b;}
>
> void ingenue()
> {D d; D* pd = &d; tricky(&pd); pd->aMethodOnlyDhadAnd_NOT_B();}
> This is, in a way, related to of the old problem that a bag-of-apples
> is-NOT-a bag-of-fruit (even if an apple is-A fruit) *under mutation*
> (because if you passed it to a function treating it as bag-of-fruit, it
> could insert in it a banana, thus violating semantic constraints [class
> invariants] of bag-of-apples). [_that_, in turn, can be more abstractly
> related to the problem that a circle is-NOT-an ellipse *under mutation*,
> because a rescale(mX,mY) would violate the semantic symmetry constraint of
> class circle...]. The presence of mutators makes is-A determinations far
> from intuitive sometimes...!
The fact that `D **' is-NOT-a `B **' is closely related to the fact that
`B **' is-NOT-a `const B **'. Both pairs fail because the referent of the
latter item can be mutated in ways not allowed by the former item.
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: John Max Skaller <maxtal@suphys.physics.su.oz.au>
Date: 1995/09/27 Raw View
Jean-Rene Bouvier <jr@isoit109.bbn.hp.com> wrote:
>In a number of libraries, the following trick is used to denote the acquisition
>of a pointer and to make it inaccessible to callers:
>
> void GrabPointer(Object*& object)
> {
> Object* obj = object;
> object = 0;
> // Now, work with obj ...
> }
>
>Callers who pass pointers to GrabPointer() will not be able - upon return from
>the function - to access the object the pointer used to refer to.
>
>This nice trick is defeated in presence of inheritance; i.e. if instead of
>passing an Object*, the caller wants to pass a DerivedObject*, a compilation
>error should be issued (at least, this is my understanding, and this is also
>what Borland 4.5 and HP 3.5 compilers do).
>
>This is very unfortunate, and it also makes the use of references to pointers
>counter-intuitive: after all, if a reference hadn't been used, passing a
>DerivedObject* would have been perfectly legal.
Nope. The conversion
DerivedObject* --> Object*
is an RVALUE conversion. The resultant Object* is an rvalue.
You cannot bind a non-const reference (argument) to an rvalue.
Think about it -- setting the a pointer variable (lvalue) known as an
Object*
to some value inside the function, when the caller knew it as
an DerivedObject* variable, would require an adjustment to the pointer
in the general case: the called function cannot know that and the
generated code would be a simple register store operation.
The resultant value would not be usable in the callers environment.
Basically, a DerivedObject* is NOT derived from an Object*.
Solution -- overloading:
void GrabPointer(DerivedObject *& x) {
Object *o = x;
GrabPointer(o);
if(!o) x = 0;
}
[you might even try a template :-]
--
John Max Skaller voice: 61-2-566-2189
81 Glebe Point Rd fax: 61-2-660-0850
GLEBE NSW 2037 email: maxtal@suphys.physics.oz.au
AUSTRALIA email: skaller@maxtal.com.au
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]