bowman@reed.UUCP (Eric Bowman) (06/29/90)
I've just discovered, to my horror, that you can't create HandleObjects with multiple base classes in MPW C++. Are there any work arounds for this? Anyone know why this is the case? Thanks, bobo bowman@reed.{bitnet,UUCP,edu} Personal to Alex Chaffee -- my email bounces. Any other addresses?
lsr@Apple.COM (Larry Rosenstein) (06/29/90)
In article <15132@reed.UUCP> bowman@reed.UUCP (Eric Bowman) writes: >I've just discovered, to my horror, that you can't create HandleObjects >with multiple base classes in MPW C++. Are there any work arounds for this? >Anyone know why this is the case? The reason is that the standard implementation of C++ multiple inheritance requires that you pass a pointer to the middle of an object's storage. That's because each class' method is compiled to access fields using fixed offsets. (If you look at the generated C code for a native C++ class, you will see that it adds an offset to the object pointer before calling a method.) Methods of HandleObject subclasses expect to be passed a handle, and it's not possible to pass a handle that refers to the middle of an object. Plus you have to worry about the handle moving if the heap compacts. One workaround is to inherit from a primary class, and delegate some functions to to instances of the secondary classes. In other words, instead of inheriting from A & B, you inherit only from A, and keep an instance of B around. Methods that need to access B's functionality do so by sending a message to the instance of B. -- Larry Rosenstein, Object Specialist Apple Computer, Inc. 20525 Mariani Ave, MS 46-B Cupertino, CA 95014 AppleLink:Rosenstein1 domain:lsr@Apple.COM UUCP:{sun,voder,nsc,decwrl}!apple!lsr
amanda@mermaid.intercon.com (Amanda Walker) (06/30/90)
In article <15132@reed.UUCP>, bowman@reed.UUCP (Eric Bowman) writes: > I've just discovered, to my horror, that you can't create HandleObjects > with multiple base classes in MPW C++. Are there any work arounds for this? > Anyone know why this is the case? The short answer is that HandleObjects, which were designed to allow compatibility with Object Pascal, are incapable of representing objects with multiple parent classes. The memory representation and method dispatching strategies in Object Pascal were only designed with single inheritance in mind. The longer answer is that C++ multiple inheritance depends on the ability to treat a pointer to a piece of an object as an object in its own right. This can be done with normal C "structs," but not with Macintosh handles. The only workaround I know of is to put a HandleObject into an instance variable of a "conventional" C++ object, with method wrappers to connect the two inheritance chains. This is kind of grody, and it still doesn't let you inherit from, say, several MacApp classes, but it's better than nothing... -- Amanda Walker InterCon Systems Corporation --
lsr@Apple.COM (Larry Rosenstein) (06/30/90)
In article <268BA8DC.4CD4@intercon.com> amanda@mermaid.intercon.com (Amanda Walker) writes: > >The short answer is that HandleObjects, which were designed to allow >compatibility with Object Pascal, are incapable of representing objects with The PascalObject class provides compatibility with Object Pascal. HandleObjects are separate from PascalObjects. They are essentially native C++ objects with the restrictions that multiple inheritance isn't allowed and the objects must be allocated on the heap. (Since multiple inheritance isn't allowed, they probably use the older & more efficient C++ runtime implementation.) There's also the class SingleObject, which also uses the older implementation, and therefore doesn't support multiple inheritance. SingleObjects are allocated on the heap as non-relocatable pointers and can be allocated on the stack. -- Larry Rosenstein, Object Specialist Apple Computer, Inc. 20525 Mariani Ave, MS 46-B Cupertino, CA 95014 AppleLink:Rosenstein1 domain:lsr@Apple.COM UUCP:{sun,voder,nsc,decwrl}!apple!lsr
chewy@apple.com (Paul Snively) (06/30/90)
In article <15132@reed.UUCP> bowman@reed.UUCP (Eric Bowman) writes: > I've just discovered, to my horror, that you can't create HandleObjects > with multiple base classes in MPW C++. Are there any work arounds for this? > Anyone know why this is the case? Larry Rosenstein and Amanda Walker have already done an excellent job of answering the question Eric poses, but I'd like to point out something else: Since Eric is using HandleObjects, he apparently isn't concerned about Object Pascal compatibility. This means that he's probably concerned about fragmenting the heap, which standard C++ objects, being based on malloc and free, tend to do. Andy Shebanow, a former engineer here in MacDTS, wrote a very good article in "D e v e l o p" describing a class that he created called "PtrObject." The idea was to provide all of the functionality of standard C++ but to use NewPtr and DisposPtr to manage memory instead of malloc and free. Perhaps Eric would benefit from using Andy's PrtObject class. Just a thought... __________________________________________________________________________ Paul Snively Macintosh Developer Technical Support Apple Computer, Inc. chewy@apple.com Just because I work for Apple Computer, Inc. doesn't mean that I believe what they believe, or vice-versa. __________________________________________________________________________
amanda@mermaid.intercon.com (Amanda Walker) (06/30/90)
In article <8937@goofy.Apple.COM>, lsr@Apple.COM (Larry Rosenstein) writes: > HandleObjects are separate from PascalObjects. Oops, you're right. However, as we both seem to have noted simultaneously, both PascalObjects and HandleObjects have the same restriction to single inheritance. -- Amanda Walker InterCon Systems Corporation --
steve@hite386.UUCP (Steve Hite) (07/02/90)
amanda@mermaid.intercon.com (Amanda Walker) writes: >In article <15132@reed.UUCP>, bowman@reed.UUCP (Eric Bowman) writes: >> I've just discovered, to my horror, that you can't create HandleObjects >> with multiple base classes in MPW C++. Are there any work arounds for this? >> Anyone know why this is the case? >The only workaround I know of is to put a HandleObject into an instance >variable of a "conventional" C++ object, with method wrappers to connect >the two inheritance chains. This is kind of grody, and it still doesn't >let you inherit from, say, several MacApp classes, but it's better than >nothing... >-- >Amanda Walker >InterCon Systems Corporation >-- Larry Rosenstein writes: >One workaround is to inherit from a primary class, and delegate some >functions to to instances of the secondary classes. In other words, instead >of inheriting from A & B, you inherit only from A, and keep an instance of B >around. Methods that need to access B's functionality do so by sending a >message to the instance of B. Eric, Amanda and Larry were kind enough to post a response to the same question I had a couple of months ago. The difference in the replies to you suggest to me that they have come up with workarounds to the problem since their discussion with me (or they already knew and forgot to mention them :-)). I bow to their experience with MacIntosh programming and I would like to suggest some additions to these. I suggest you read T.A. Cargill's article in the 1990 Usenix C++ Conference Proceedings entitled "Does C++ Really Need Multiple Inheritance?" starting on page 315. T.A. Cargill's conclusion paragraph states: "In the majority of published examples, multiple inheritance in C++ is not required to express programs. In most cases a single inheritance solution is simpler - inheritance from a class being replaced by the embedding of an object. In light of this we should view multiple inheritance in C++ as a large scale research project, in which we must evaluate its usefulness and weigh it's costs. The results to date suggest that multiple inheritance is not paying its way." Also, Grady Booch states in "Object Oriented Design w/Applications" on pp 110-111: The Meaning of Multiple Inheritance Relationships Among Classes "...The need for multiple inheritance in object oriented programming languages is still a topic of great debate. In our experience, we find multiple in- heritance to be like a parachute: you don't always need it, but when you do, you're really happy to have it on hand..." I believe Larry and T.A. Cargill are saying the same thing. Amanda is losing me at the point "...method wrappers to connect the two inheritance chains". I would need to see an example of this because I'm shooting blanks trying to visualize it. From what I've read, I don't consider their approach (Larry and T.A.) a "kluge" to get around a machine-dependent feature such as HandleObject. Rather, it's a different way of looking at the problem from a design standpoint. If you still believe that you have relationships that *must* be implemented with MI then I would answer that there is not a well thought-out way yet of programming this in C++ on the MacIntosh without fragmenting the heap. Definitely get Grady Booch's new book I just mentioned and the three C++ Usenix volumes that are a very good reference for exploratory experiences and findings in C++ implementations. ------------------------------------- Steve Hite ...gatech!uflorida!unf7!hite386!steve
amanda@mermaid.intercon.com (Amanda Walker) (07/03/90)
In article <37@hite386.UUCP>, steve@hite386.UUCP (Steve Hite) writes: > Amanda > is losing me at the point "...method wrappers to connect the two inheritance > chains". I would need to see an example of this because I'm shooting blanks > trying to visualize it. Sorry about that :-). I guess I forgot to translate my thoughts into English before I typed them in. What I was suggesting is the same thing Larry did: having a C++ object (let's call it "a") with HandleObjects as instance variables (let's call them "b" and "c"). My phrase "method wrapper" means that "a" has methods that invoke the corresponding method from "b" or "c". Since "a" is not actually a subclass of either "b" or "c", you have to manually pass the methods along, instead of having it done automatically by the inheritance tree built by the compiler & linker. It's clumsier that "real" multiple inheritance, but it might be enough for many applications... -- Amanda Walker InterCon Systems Corporation -- "I can only assume this is not the first-class compartment." --Hitchhiker's Guide to the Galaxy
beard@ux5.lbl.gov (Patrick C Beard) (07/16/90)
Here is how I use Handles and C++ objects together without fragmenting heaps. This allows full C++ style objects with single and multiple inheritance. // overloaded storage operators. Allows floating C++ objects. void* operator new(size_t size) { Handle h = NewHandleClear((long)size); if(!h || MemError() != noErr) return nil; MoveHHi(h); return (void*)*h; } operator delete(void* p) { if(p) { Handle h = RecoverHandle((Ptr)p); DisposHandle(h); } } Using these storage operators, create an object like so: MyClass **h_instance, *p_instance; p_instance = new MyClass; h_instance = RecoverHandle((Ptr)p_instance); Now, you can refer to the object henceforth using h_instance, which you can cast to a handle and perform standard locking and unlocking before and after use. For example: (**h_instance).MyMethod(); // be sure to lock if necessary! -- ------------------------------------------------------------------------------- - Patrick Beard, Macintosh Programmer (beard@lbl.gov) - - Berkeley Systems, Inc. ".......<dead air>.......Good day!" - Paul Harvey - -------------------------------------------------------------------------------