Topic: Is it planned to add an "go-one-level-up-in-collection" operator to the language?
Author: "Thomas Szuecs" <Thomas.Szuecs@Informatik.TU-Chemnitz.DE>
Date: 1997/12/07 Raw View
Barry Margolin <barmar@bbnplanet.com> wrote in article
<65tllr$nu8@pasilla.bbnplanet.com>...
> In article <01bcfc0a$500ec8f0$01000086@tsz>,
> Thomas Szuecs <Thomas.Szuecs@Informatik.TU-Chemnitz.DE> wrote:
> >I mean the whole thing has a motivation. In real life
> >an object is aware about where it is part of and so
> >it can make use of it without asking a "public method"
> >of god to forward its request down all the hierarchy
> >long nor maintaining pointers to all the thousands of
> >objects that hierarchy.
>
> In real life, an object may be an element of a number of collections and
> hierarchies. For instance, a person may be an employee of a company, a
> member of a family, etc. Which of these collections should the "go up"
> function refer to?
To the one where it points to at run-time, of course.
In OOE there exist many different relations between constructs of this
concept. Most common is the class-class relation (inheritance), but there
also exist many other, such as class-object, which is called "part-of" (an
object is part of a class here - there also exists the object-object
"part-of" relation).
You are right. This cannot be checked at compile-time, because when the
compiler looks at a class's source code it cannot determine which objects
might be created from that class all over the rest of the source code.
In your example the code in a method of this "person" class would have to
check where he/she is part of before a method of the family class or the
company class is called. This can be done very easily with RTTI.
With letting the class behave as appropriate in a certain situation we
place the intelligence inside of exactly that class and not in the
surrounding ones. This is more in the sense of OOE than C++ does at
the moment.
--
cu,
Thomas
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1997/12/10 Raw View
Thomas Sz cs wrote:
>
> >> > I mean the whole thing has a motivation. In real life
> >> > an object is aware about where it is part of and so
> >> > it can make use of it without asking a "public method"
> >> > of god to forward its request down all the hierarchy
> >> > long nor maintaining pointers to all the thousands of
> >> > objects that hierarchy.
> >>
> >> In general, an object shouldn't be aware of what it is
> >> part of. Otherwise, it depends upon what is outside
> >> itself, and really isn't a distinct object from a
> >> logical point of view.
>
> This is true for a class as a scheme for a concept, but not
> for an instance or particular realization of that concept
> (aka an object). I know, the UI example is a bit weak to
> stress the need for such a language feature, but there are
> other concerns that should be considered.
>
> Let's take a real world and every-day life example. The
> class for a human could be CHuman and some of them could
> be part of a group (CGroup here). CGroup is only an abstract
> base class in our example, because there exists two more
> specialized types of groups CGroupA and CGroupB. A human
> can be part of any of these two groups.
>
> class CHuman
> {
> void foo();
> };
>
> class CGroup { ... }; //has as least one virt. method
> class CGroupA : public CGroup { ... };
> class CGroupB : public CGroup { ... };
>
> Method foo() might now want to send special messages
> depending on in which group it is:
>
> void CHuman::foo()
> {
> if ( typeid(*(this^)) == typeid(CGroupA) )
> {
> //do something special
> } else
> {
> if ( typeid(*(this^)) == typeid(CGroupB) )
> {
> //do something special in that case
> };
> };
>
Now, look at real life: How do you know in which group(s) you are?
Only because someone told you ,and you remembered it.
The programming analogy of telling it to you is to give a pointer,
and the analogy to remembering it is to store the pointer inside the
object.
And of course you are responsible yourself to recognise in which group
you are, and what you may tell them.
[...]
> >> > For actual programming this means that i.e. a button
> >> > of a separate area of a dialog, which is also again
> >> > part of a window (with many other child windows and
> >> > dialogs) does not need to call that window all the
> >> > time nor to maintain pointers to all these ui elements,
> >> > containers and whatever..
> >>
> >> First of all, when a button is part of a window, that
> >> doesn't typically mean that the button object is part of
> >> (i.e., a base class of) the window object.
>
> The button is course not a base class the window object..
> This wouldn't be very wise.. :))
>
It's most probably not a member either - you might want to
have different buttons in different windows. And I don't think
subclassing for each layout would be a good idea. (And what
if you want to change a window at runtime?)
[...]
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: "Thomas Sz cs" <Thomas.Szuecs@Informatik.TU-Chemnitz.DE>
Date: 1997/12/01 Raw View
>> > I mean the whole thing has a motivation. In real life
>> > an object is aware about where it is part of and so
>> > it can make use of it without asking a "public method"
>> > of god to forward its request down all the hierarchy
>> > long nor maintaining pointers to all the thousands of
>> > objects that hierarchy.
>>
>> In general, an object shouldn't be aware of what it is
>> part of. Otherwise, it depends upon what is outside
>> itself, and really isn't a distinct object from a
>> logical point of view.
This is true for a class as a scheme for a concept, but not
for an instance or particular realization of that concept
(aka an object). I know, the UI example is a bit weak to
stress the need for such a language feature, but there are
other concerns that should be considered.
Let's take a real world and every-day life example. The
class for a human could be CHuman and some of them could
be part of a group (CGroup here). CGroup is only an abstract
base class in our example, because there exists two more
specialized types of groups CGroupA and CGroupB. A human
can be part of any of these two groups.
class CHuman
{
void foo();
};
class CGroup { ... }; //has as least one virt. method
class CGroupA : public CGroup { ... };
class CGroupB : public CGroup { ... };
Method foo() might now want to send special messages
depending on in which group it is:
void CHuman::foo()
{
if ( typeid(*(this^)) == typeid(CGroupA) )
{
//do something special
} else
{
if ( typeid(*(this^)) == typeid(CGroupB) )
{
//do something special in that case
};
};
Sure, it must be a design decision if such an approach
makes sense in a particular case or not. There should
also be a chance to switch this system completely off.
I know, for a class it does not mean anything what will
be outside of it at run-time, but it can be for an actual
object. I don't want to play tricks. The above could also
be achieved with a pointer to the base class CGroup inside
of CHuman. The programmer would have to take care for
everything then. Since such situations (child in part-of
hierarchy needs access to parent functionality) don't only
happen once in 10 years I propose that shifting the
reposibility from the programmer to the language could
lead to less bugs and source code that is easier to read
and to understand.
>> > For actual programming this means that i.e. a button
>> > of a separate area of a dialog, which is also again
>> > part of a window (with many other child windows and
>> > dialogs) does not need to call that window all the
>> > time nor to maintain pointers to all these ui elements,
>> > containers and whatever..
>>
>> First of all, when a button is part of a window, that
>> doesn't typically mean that the button object is part of
>> (i.e., a base class of) the window object.
The button is course not a base class the window object..
This wouldn't be very wise.. :))
>> Instead, they're completely separate objects that have
>> application-defined references to each other.
>>
>> That a button knows about the window that contains it
>> is purely an aspect of the application. Therefore, it
>> is the application that should provide a means for
>> getting from the button to its enclosing window, not
>> the language.
This much depends on the view... C++ is a very compile-
time check focused language. Some recent additions like
RTTI now allow certain run-time checks. In the case of
RTTI we can get information about the class an object
was made of or if a class is base class of another class.
So we can get "inherited from" info at run-time.
What we still cannot determine is the important "part-of"
aspect. "Part-of" is purely an object dependent thing,
not a class dependent one. There the language lacks.
>> How could the language know that the immediate parent
>> was something the programmer should even be interested
>> in? For instance, in the case of a dialog box, the
>> button may not be a child of the dialog, but might
>> instead be a child of an uninteresting framing rectangle
>> that is in turn a child of the window.
You are right.. this is run-time object information and
not static compile-time class data. Since it is not enough
to just use the button (an method - OnClick - or whatever
needs to be overloaded to achieve something or there must
be a big method inside of the dialog or whatever contains
the button, which takes care of what will happen after a
click at the buttons). We implemented here an UI system
that is able to do its job in O(1) in nearly all cases and
beats algorithms such as dirty rect many times. It makes
solely use of classes that know about their parent ui
element and are through that completely aware of themselves.
With a language addition for the part-of relation we could
reduce the amout of code to be written by a considerably
amount and would also enhance readability (aka "what's this
pointer for" vs. "ahh.. the parent is accessed").
>> The programmer would be much happier with a direct
>> application-defined pointer to the window in the button
>> object, than using some blind language construct to
>> follow the inheritance chain.
No inheritance chain here at all.. it's the part-of chain.
>> That said, I _would_ like to see some type decoding
>> support added to the language. In particular, given a
>> typeinfo object for a derived type, it would be nice if
>> there was a standard way to ask such questions as:
>>
>> 1) Is it a scalar or class type?
>>
>> 2) Is it const, volatile, neither or both?
>>
>> 3) Is it a function or an object?
>>
>> 4) If it's a class type, what's its first base class?
>>
>> 5) Given a class and one of its bases, what's its next
>> base class?
>>
>> 6) Is a particular base class virtual?
>>
>> and so on.
I see what you mean and tend to agree for most of them.
This could be handy for exchanging data between different
applications made by different programmers. although this
would be a very high-level support.
>> All this information has to exist anyway inside the
>> implementation for the exception handling mechanism to
>> work, so why not nail it down so the programmer can get
>> at it? I wouldn't attempt to use it for dealing with
>> dialog boxes and buttons, but I might well use it in
>> writing an object-oriented operating system that wants
>> to include some debugging support in it, or something
>> like that.
Yes.
--
cu,
Thomas
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Barry Margolin <barmar@bbnplanet.com>
Date: 1997/12/01 Raw View
In article <01bcfc0a$500ec8f0$01000086@tsz>,
Thomas Szuecs <Thomas.Szuecs@Informatik.TU-Chemnitz.DE> wrote:
>I mean the whole thing has a motivation. In real life
>an object is aware about where it is part of and so
>it can make use of it without asking a "public method"
>of god to forward its request down all the hierarchy
>long nor maintaining pointers to all the thousands of
>objects that hierarchy.
In real life, an object may be an element of a number of collections and
hierarchies. For instance, a person may be an employee of a company, a
member of a family, etc. Which of these collections should the "go up"
function refer to?
--
Barry Margolin, barmar@bbnplanet.com
GTE Internetworking, Powered by BBN, Cambridge, MA
Support the anti-spam movement; see <http://www.cauce.org/>
Please don't send technical questions directly to me, post them to newsgroups.
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Pete Becker <petebecker@acm.org>
Date: 1997/11/25 Raw View
Paul D. DeRocco wrote:
>
> Thomas Sz cs wrote:
> >
> >
> > class collection
> > {
> > element_a a;
> > element_b b;
> > };
> >
> > collection collobject;
> >
> > Now, it's not so convienient to access element_a::foo()
> > of object collobject.a from collobject.b.
>
> It shouldn't be convenient. In fact, it shouldn't be possible. There's nothing
> to guarantee that an element_b is actually paired with an element_a in this
> manner.
Right.
>
> If the objects are polymorphic, dynamic_cast will go from one to the other if
> possible, or give you a null pointer if it isn't.
Nope. You can get from one base to another with dynamic_cast, but not
from member to member.
-- Pete
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: "Thomas Sz cs" <Thomas.Szuecs@Informatik.TU-Chemnitz.DE>
Date: 1997/11/29 Raw View
Paul D. DeRocco <pderocco@ix.netcom.com> wrote in article
<347934C7.E17DA880@ix.netcom.com>...
> Thomas Sz cs wrote:
> >
> > Suppose the following definitions:
> >
> > class element_a
> > {
> > public:
> > void foo();
> > };
> >
> > class element_b
> > {
> > public:
> > void bar();
> > };
> >
> > class collection
> > {
> > element_a a;
> > element_b b;
> > };
> >
> > collection collobject;
> >
> > Now, it's not so convienient to access element_a::foo()
> > of object collobject.a from collobject.b.
>
> It shouldn't be convenient. In fact, it shouldn't be
> possible. There's nothing to guarantee that an element_b
> is actually paired with an element_a in this manner.
Right.. and that's why it can't be done without language
support. A possible solution could be to add a pointer to
an object that points to the current parent (in terms of
part-of-hierarchy - not inheritance).
I know, it is impossible for the compiler to decide who
will be the actual parent at run-time. So this would be
a true run-time matter as it is e.g. with virtual dtors
and could work the following way:
When the ctor gets called this pointer (let's call it
vparent) will be initialized too with the address of the
parent of this object (not the class!) in the part of
hierarchy. This would mean that the the parent has to
pass it's address to the ctor of all it's members, which
are an instance of any class. This should be rather
simple. The tougher thing comes now:
For the code in the methods, which want to use this
system the actual address of the parent's method to
be called has to determined. The following two ways
are possible to go:
1. Explicit
At compile time the programmer has to specify who the
parent is that particular case. This could be done by
using a simple cast operation:
((collection*)^)->a.foo(); //assuming the example
This would be short for:
((collection*)this^)->a.foo();
The generated code at this place would now simply do
what it has been always doing.. :-))
2. Implicit
At run-time we know who the current parent is. This
information should be passed to the object when it
is being constructed. So the run-time system would
do an implicit cast to "collection*", test if this
class has a property "a" that is of type "element_a"
and then call it. I don't like that.. looks very
complicated and not worth the hassle..
I mean the whole thing has a motivation. In real life
an object is aware about where it is part of and so
it can make use of it without asking a "public method"
of god to forward its request down all the hierarchy
long nor maintaining pointers to all the thousands of
objects that hierarchy.
For actual programming this means that i.e. a button
of a separate area of a dialog, which is also again
part of a window (with many other child windows and
dialogs) does not need to call that window all the
time nor to maintain pointers to all these ui elements,
containers and whatever..
Sure, access should be limited. It should be possible
by default to access everything in the parent and
good style would be to only use the methods of the
parent to change one of its properties..
--
cu,
Tom
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: "Paul D. DeRocco" <pderocco@ix.netcom.com>
Date: 1997/11/30 Raw View
Thomas Sz cs wrote:
>
> I mean the whole thing has a motivation. In real life
> an object is aware about where it is part of and so
> it can make use of it without asking a "public method"
> of god to forward its request down all the hierarchy
> long nor maintaining pointers to all the thousands of
> objects that hierarchy.
In general, an object shouldn't be aware of what it is part of. Otherwise, it
depends upon what is outside itself, and really isn't a distinct object from a
logical point of view.
> For actual programming this means that i.e. a button
> of a separate area of a dialog, which is also again
> part of a window (with many other child windows and
> dialogs) does not need to call that window all the
> time nor to maintain pointers to all these ui elements,
> containers and whatever..
First of all, when a button is part of a window, that doesn't typically mean
that the button object is part of (i.e., a base class of) the window object.
Instead, they're completely separate objects that have application-defined
references to each other.
That a button knows about the window that contains it is purely an aspect of
the application. Therefore, it is the application that should provide a means
for getting from the button to its enclosing window, not the language. How
could the language know that the immediate parent was something the programmer
should even be interested in? For instance, in the case of a dialog box, the
button may not be a child of the dialog, but might instead be a child of an
uninteresting framing rectangle that is in turn a child of the window. The
programmer would be much happier with a direct application-defined pointer to
the window in the button object, than using some blind language construct to
follow the inheritance chain.
That said, I _would_ like to see some type decoding support added to the
language. In particular, given a typeinfo object for a derived type, it would
be nice if there was a standard way to ask such questions as:
1) Is it a scalar or class type?
2) Is it const, volatile, neither or both?
3) Is it a function or an object?
4) If it's a class type, what's its first base class?
5) Given a class and one of its bases, what's its next base class?
6) Is a particular base class virtual?
and so on.
All this information has to exist anyway inside the implementation for the
exception handling mechanism to work, so why not nail it down so the programmer
can get at it? I wouldn't attempt to use it for dealing with dialog boxes and
buttons, but I might well use it in writing an object-oriented operating system
that wants to include some debugging support in it, or something like that.
--
Ciao,
Paul
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: "Thomas Sz cs" <Thomas.Szuecs@Informatik.TU-Chemnitz.DE>
Date: 1997/11/23 Raw View
Suppose the following definitions:
class element_a
{
public:
void foo();
};
class element_b
{
public:
void bar();
};
class collection
{
element_a a;
element_b b;
};
collection collobject;
Now, it's not so convienient to access element_a::foo()
of object collobject.a from collobject.b. I know, with
a simple pointer there's isn't any problem anymore, but
that overhead every programmer has to do over and over
+ the wierd #include dependencies could be replaced by
a nice little operator. As far as I know there was a
version of LISP that had such a mechanism. Let's call
this operator "^" for now.
element_b::bar() would look like this then:
void element_b::bar()
{
^->a.foo(); //short for "this^->a.foo()"
};
Has a similar language feature already been planned?
cu,
Tom
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: "Paul D. DeRocco" <pderocco@ix.netcom.com>
Date: 1997/11/24 Raw View
Thomas Sz cs wrote:
>
> Suppose the following definitions:
>
> class element_a
> {
> public:
> void foo();
> };
>
> class element_b
> {
> public:
> void bar();
> };
>
> class collection
> {
> element_a a;
> element_b b;
> };
>
> collection collobject;
>
> Now, it's not so convienient to access element_a::foo()
> of object collobject.a from collobject.b.
It shouldn't be convenient. In fact, it shouldn't be possible. There's nothing
to guarantee that an element_b is actually paired with an element_a in this
manner.
If the objects are polymorphic, dynamic_cast will go from one to the other if
possible, or give you a null pointer if it isn't.
--
Ciao,
Paul
---
[ 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 ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]