Topic: Why isn't there something like Become in C++ ?


Author: almog@esi.co.il
Date: 1997/02/13
Raw View
This question might be really stupid so i apologize in advance.
I have been using C++ for 3 years but i'm not into it's internals so i
might be missing something ,i asked some friends about this and
we are all wondering why is this not possible.

Why doesn't C++ include something like this?

class Foo {
 public
  Foo(Bar B);
   ..... // Members
 private:
   ..... // Members
};

class Bar {
 public
   ..... // Members
 private:
   ..... // Members
};

void main()
{
 Bar B;
 B.SomeMethod();
 if (B.SomeOtherMethod())
  become(B,Foo);
 B.SomeMethod();
}

What become will do is:
1. invoke the constructor for Foo with Bar as the parameter
2. delete Bar and call the destructor.

What's the advantage?
Full polymorphism ,unrelated objects can have similar behaviors.

What's the advantage compared to the usual C++ polymorphism?
The C++ polymorphism requires some design in advance in order
to be incorporated into large project's the class hierarchy must be
well though. When i'm using other peoples code they don't always
choose a good OO design so i can't take advantage of the significant
code reuse of polymorphism which is where this method can excel.

What's the disadvantages?
Well as far as i can tell this will be slow, and  it's not as good
as a well designed class hierarchy.

I know this can be hacked with the existing language model but
this will be (in my opinion) a very strong language feature.

I have 2 questions:
1. Can this be done without breaking the C++ paradigm?
2. How useful do you think this will be?
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: "Larry Brasfield" <larrybr@earthlink.net>
Date: 1997/02/14
Raw View
almog@esi.co.il wrote in article <E5JI7F.HJt@actcom.co.il>...
> This question might be really stupid so i apologize in advance.
> I have been using C++ for 3 years but i'm not into it's internals so i
> might be missing something ,i asked some friends about this and
> we are all wondering why is this not possible.

It's probably missing for the same reason there
is no "come_from" counterpart to "goto".

> Why doesn't C++ include something like this?
>
> class Foo {
[members elided]
> };
> class Bar {
[members elided]
> };
>
> void main()
> {
>  Bar B;
>  B.SomeMethod();
>  if (B.SomeOtherMethod())
>   become(B,Foo);
>  B.SomeMethod();
> }
>
> What become will do is:
> 1. invoke the constructor for Foo with Bar as the parameter
> 2. delete Bar and call the destructor.
>
> What's the advantage?
> Full polymorphism ,unrelated objects can have similar behaviors.
Neat, I guess.  I don't think deleting bar makes sense.  There
is the little problem of whether the storage allocated for B
is enough to hold a Foo object.  If you had "hacked with the
existing language model" (as you say) to do this, you would end
up using a placement new and this issue would stare you in the
face.  Also, if you are willing to do this a little differently,
it is not any kind of hack and better expresses what is going
on.  (Remember, your B object changed type midstream.  Even if
a compiler can keep things straight, (which will be impossible
should these changes become dependent on runtime behavior and
may not even occur in the present translation unit), we poor
humans will have a harder time with it.)  Better to write:

class FooOrBar { public:
  virtual ~FooOrBar() {}
};
class Foo : public FooOrBar { public:
  ~Foo() {}
  Foo(FooOrBar &);
  static void become(FooOrBar *& pfb) {
    Foo * pf = new Foo(*pfb);
    delete pfb;
    pfb = pf;
};
class Bar; // (similar to Foo)
void DoStuff()
{
  FooOrBar * pfb = new Bar;
  Foo::become(pfb);
}

> What's the advantage compared to the usual C++ polymorphism?
> The C++ polymorphism requires some design in advance in order
> to be incorporated into large project's the class hierarchy must be
> well though. When i'm using other peoples code they don't always
> choose a good OO design so i can't take advantage of the significant
> code reuse of polymorphism which is where this method can excel.
Select better code for reuse.  You cannot put new paint
on a rotting surface and expect it to stay pretty.

> What's the disadvantages?
> Well as far as i can tell this will be slow, and  it's not as good
> as a well designed class hierarchy.
>
> I know this can be hacked with the existing language model but
> this will be (in my opinion) a very strong language feature.
>
> I have 2 questions:
> 1. Can this be done without breaking the C++ paradigm?
Yes.
> 2. How useful do you think this will be?
confusing and impossible to implement, therefore not useful
--
-- Larry Brasfield
The aforementioned views are mine alone.
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: John Lilley <jlilley@empathy.com>
Date: 1997/02/16
Raw View
almog@esi.co.il wrote:

> Why doesn't C++ include something like this?
>
> class Foo { ... };
> class Bar { ... };
>
> void main()
> {
>         Bar B;
>         B.SomeMethod();
>         if (B.SomeOtherMethod())
>                 become(B,Foo);
>         B.SomeMethod();
> }
>
> What become will do is:
> 1. invoke the constructor for Foo with Bar as the parameter
> 2. delete Bar and call the destructor.

> I have 2 questions:
> 1. Can this be done without breaking the C++ paradigm?

Yes and no.  A difference between C++ and more strongly OO languages
like SmallTalk and Java is that it has objects that are "by value" as
opposed to "by reference".  This means that the storage and layout of
the object is, in this example, on the stack.  In Java, a similar
construct would allocate a new object on the heap and just have the
reference (i.e. pointer) on the stack.  So in C++ this is intractible
because of the physical memory layout requirements (Foo may not be the
same size as Bar).  C++ also allows objects to expose pointers to their
internals, so it would be a problem if you copied a pointer internal
member and then morphed the object.  In Java this is not a problem
because of GC.

There are also differences in binding time.  In a stronger OO language,
the binding of a name to it's meaning can be deferred until runtime, so
you can invoke a method of an object without knowing what the object
"really" is.  In C++, binding is static, so the only way you get
ploymorphism is with virtual methods, and that in turn requires
inheritance.

So in C++ you can get somewhat similar sementics via:

   class Foo : public Bar { ... };
   Bar *B = new Bar;
   B->DoSomething();
   if (B->DoSomethingElse())
   {
      Bar *B2 = new Foo(...);
      delete B;
      B = B2;
   }
   ...


> 2. How useful do you think this will be?

Somewhat limited, due to the fact that anyone pointing to the "old"
object will be left with a dangling pointer.  However, with some clever
wrapper objects this may be more useful.  It seems that Coplien had some
examples of this sort of thing.

john lilley
---
[ 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: seurer@rchland.ibm.com (Bill Seurer)
Date: 1997/02/18
Raw View
In article <E5JI7F.HJt@actcom.co.il>, almog@esi.co.il writes:
|> class Foo {
|>  public
|>   Foo(Bar B);
|>    ..... // Members
|>  private:
|>    ..... // Members
|> };
|>
|> class Bar {
|>  public
|>    ..... // Members
|>  private:
|>    ..... // Members
|> };
|>
|> void main()
|> {
|>  Bar B;
|>  B.SomeMethod();
|>  if (B.SomeOtherMethod())
|>   become(B,Foo);
|>  B.SomeMethod();
|> }

Suppose you had a whole bunch of these "become" things.  When the compiler
reaches the "B.SomeMethod()" point how can it check if that is a valid
statement?  Would it have to keep track of all the becomes and look
through all of them to make sure that every type had a SomeMethod method
and the same data layout?
--

- Bill Seurer     ID Tools and Compiler Development      IBM Rochester, MN
  BillSeurer@vnet.ibm.com                               BillSeurer@aol.com
  Home page:  http://members.aol.com/BillSeurer
---
[ 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: jdege@jdege.visi.com (Jeffrey C. Dege)
Date: 1997/02/18
Raw View
On 18 Feb 97 03:19:43 GMT, Bill Seurer <seurer@rchland.ibm.com> wrote:
>
>Suppose you had a whole bunch of these "become" things.  When the compiler
>reaches the "B.SomeMethod()" point how can it check if that is a valid
>statement?  Would it have to keep track of all the becomes and look
>through all of them to make sure that every type had a SomeMethod method
>and the same data layout?

Forget all of that.  Suppose, for example, the compiler _could_
automagically change an object from one type to another.  It'd _still_
be a bad idea.  If your object model involves objects changing type,
you've got a bad object model.

Take the typical person with subtypes example.  Your model might
have employee subtypes person and customer subtypes person, etc.
You might then want to say that as of the hire date a customer
becomes an employee.  It's a lousy model.  What happens when a
person acts as both customer _and_ as employee?  Where do you
track the date on which a person became an employee?

A better model has employee and customer being subtypes of role,
where a person performs one or more roles.  The roles performed
by a particular person will likely change over time.  But a
person remains a person and a role remains a role.

--
The most exciting phrase to hear in science, the one that heralds new
discoveries, is not "Eureka!" ("I found it!") but rather "hmm....that's
funny..."  --   Isaac Asimov
---
[ 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: Marcelo Cantos <marcelo@mds.rmit.edu.au>
Date: 1997/02/19
Raw View
Jeffrey C. Dege wrote:
>
> On 18 Feb 97 03:19:43 GMT, Bill Seurer <seurer@rchland.ibm.com> wrote:
> >
> >Suppose you had a whole bunch of these "become" things.  When the compiler
> >reaches the "B.SomeMethod()" point how can it check if that is a valid
> >statement?  Would it have to keep track of all the becomes and look
> >through all of them to make sure that every type had a SomeMethod method
> >and the same data layout?
>
> Forget all of that.  Suppose, for example, the compiler _could_
> automagically change an object from one type to another.  It'd _still_
> be a bad idea.  If your object model involves objects changing type,
> you've got a bad object model.

What about an int object that becomes a real object?  Or a real
object that becomes a complex object?

I do agree, however, that mutating the type of objects themselves
is not the answer.  This type of problem is better solved by a
variation of the envelope/letter idiom.

>
> Take the typical person with subtypes example.  Your model might
> have employee subtypes person and customer subtypes person, etc.
> You might then want to say that as of the hire date a customer
> becomes an employee.  It's a lousy model.  What happens when a
> person acts as both customer _and_ as employee?  Where do you
> track the date on which a person became an employee?

Multiple inheritance!  (Just kidding)

>
> A better model has employee and customer being subtypes of role,
> where a person performs one or more roles.  The roles performed
> by a particular person will likely change over time.  But a
> person remains a person and a role remains a role.

I agree. "customer" and "employee" are attribute of a person which
may change over time in real life.  However, the object model
should be based on the problem domain and not attempt to model all
of the diversity that life exhibits.  Hence, if someone is writing
a personnel management package, there is no reason not to create an
employee class which is derived from a person class.  If a person
ceases to be an employee, the object is either destroyed or tagged
invalid.  This models the problem domain better than a person class
with an employee attribute.


--
___________________________________________________________________
Marcelo Cantos, Research Assistant          marcelo@mds.rmit.edu.au
Multimedia Database Systems Group    __/_      _ Tel 61-3-9282-2497
723 Swanston St, Carlton VIC 3053, Aus/ralia ><_>Fax 61-3-9282-2490
                                     /
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]