dmg@ssc-vax.UUCP (David Geary) (04/15/89)
Although I am quite experienced in C, I have never written one line of code in C++ (or any other ool), although I expect that to change in the near future. Anyway, I am very interested in object oriented programming, and C++. I would like to start a discussion concerning C++ and ool's. I would like to see comparisons of C++ vs. other object oriented languages such as: C++ vs. Modula2 C++ vs. Lisp C++ vs. SmallTalk C++ vs. Prolog C++ vs. Objective C I'd like to know how C++ stacks up against the others as far as: It's degree of "object-orientedness" Speed and portability. It seems to me that C++ is not as "object-oriented" as Lisp, SmallTalk, and the like, but then again, realize that I don't know what I'm talking about ;-). Also, it seems that C++ would be more efficient, and more easily portable than the "others", but, then again ... -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~ David Geary, Boeing Aerospace, Seattle ~ ~ "I wish I lived where it *only* rains 364 days a year" ~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
alan@rnms1.paradyne.com (Alan Lovejoy) (04/19/89)
In article <2602@ssc-vax.UUCP> dmg@ssc-vax.UUCP (David Geary) writes: >I would like to start a discussion concerning C++ and ool's. I would >like to see comparisons of C++ vs. other object oriented languages such as: > >C++ vs. Modula2 >C++ vs. Lisp >C++ vs. SmallTalk >C++ vs. Prolog >C++ vs. Objective C > > I'd like to know how C++ stacks up against the others as far as: > >It's degree of "object-orientedness" >Speed and portability. -- Portability -- 1) Language portability is a function of how similar the compilers for different systems are and the breadth and depth of STANDARD functions that are provided via STANDARD interfaces. This is largely an extra-linguistic issue that has more to do with the history and culture of different language communities than it has to do with the technical merits of languages as languages. Smalltalk is the winner here, with C++ a strong runner-up. 2) The other issue is how many different systems have implemantions of your language available. C++ wins hands down on this point. -- Speed -- Speed is just as much an implementation issue (compiler AND host CPU) as it is a function of the language (syntax, semantics). Actually, I don't think syntax has any effect on speed at all, unless the translation and execution of the program are both being timed (e.g., an interpretive implementation). The semantics of a language affect speed of execution in several ways: 1) Whether values can be computed during language translation or only during program execution (e.g., dynamic vs. static binding, where the "value" being computed is the address of the object/function which is being referenced). C++ and Modula-2 are essentially tied for first place on this one. 2) How close the expression of an algorithm and/or data structure can be to its mathematically optimum form. Bit manipulation in a language that doesn't know how to talk about bits may suffer a performance penalty. The performance penalty comes from the extra work that must be done in order to simulate what you really wanted to do using something else as a model. The extra work can involve both translations between different representations and adjusting for the differences between the actual behavior of your model and the object/process being modeled. No clear winner is evident, but C++ may have it by a nose. 3) The amount of information that can be provided to the code generator and/or optimizer about the intended use/semantics of objects. Optimization depends upon knowing invariants. If the places from which a variable is referenced are always computable at translation time, then the variable can be kept in a register. Otherwise, it cannot, because the points of access to the value of the variable are not known to be invariant at translation time. Modula-2 has the edge on this metric. 4) The semantic distance between the operations/data structures provided by the source language and the target language (e.g., the machine language). The greater the distance between the semantics of the source langauge and target language operations, the more target language operations will be necessary in order to express the semantics of each source language operation. However, because the space in which this "semantic distance" is measured is multidimensional, it is important to consider along what dimension(s) this distance lies. The semantic distance between integer addition and floating point addition is not in the same dimension as the semantic distance between floating point addition and floating point vector addition, which is in a dimension I will call primitiveness. Floating point addition is more primitive than floating point vector addition. Or to state it conversely, vector addition is "higher level" than scalar addition. The greater the semantic distance between the primitiveness of the source and target languages (assuming the source language is less primitive than is the target language), the more opportunity there is for optimization of translations. This is because the relative semantic granularity of the target language with respect to the source langauge is a function of the difference in primitiveness level. Greater granularity permits greater flexibility in tailoring translations so that they precisely express the semantics of the source construct without unwanted/unnecessary side effects. And the fact that larger differences in primitiveness mean more target operations for each source operation is mitigated by the fact the work performed by the target language operations is inherent to the definition of the source operation, because of the definition of primitiveness. There is no such thing as a free lunch. On the other hand, the implementation of unsigned 32-bit integer math on a machine that only has signed 32-bit integer arithmetic operations would exhibit the opposite effect. The semantic distance may require multiple machine operations for some or all unsigned integer operations in the source. The unwanted side-effects of the semantics of signed integer arithmetic have to be compensated for by means of additional target language operations. The extra work is not inherent to the semantics of unsigned integer arithmetic. Therefore, the extra work is a performance loss. Prolog, Lisp, Smalltalk, Objective-C, Modula-2, C++, in that order. Disclaimer: my evaluation of the languages above is based on my estimation of what could be done with ideal compilation technology. Your mileage may vary, etc. -- Object Orientation -- I don't see object orientation as an end in itself, but rather as a tool for designing languages with great abstractive power. To me, the quality of a language is a function of its ability to EFFICIENTLY and SURELY define, express, manipulate and implement abstractions. However, now is not the time to write my doctoral dissertation of programming language design. This posting is long enough already. The definition of "object oriented language" is open to debate. Instead of debating the minimum set of attributes that an object-oriented language should have, it is more instructive to consider the ideal case. First, some definitions: A class is a set of values and the functions/relations defined on the members of that set. An object is an instance of a class which represents one of the values in the set, that is, one of values of the class. Inheritance is the ability to define a new class in terms of its differences (extensions, deletions, changes) from some other pre-existing class. Prolog, Lisp, Smalltalk, Objective-C, C++, Modula-2 The ideal object-oriented language would: 1) Have user-definable classes. Smalltalk, Objective-C and C++ satisfy this requirement. Lisp and Prolog permit the programmer to define his own class mechanism. There are versions that come with classes built in. Modula-2 has modules, but these differ from true classes because they cannot be instantiated. A module with exports a single opaque type almost qualifies as a class, but it's an ugly and inelegant class at best. Whatever it is, it does not allow class inheritance, a fatal flaw. 2) Have class inheritance. Smalltalk, Objective-C and C++ satisfy this requirement. Lisp and Prolog permit the programmer to include an inheritance mechanism in the implementation of classes. Modula-2 does not support inheritance at all. 3) Allow function/operator overloading. Smalltalk, Objective-C and C++ satisfy this requirement. Lisp and Prolog permit this to be constructed as part of the implementation of classes. The best Modula-2 can do to emulate this is by dynamically binding procedures to procedure variables: it's very, very ugly and suffers from severe limitations. 4) Be completely polymorphic. This is actually the most important requirement for abstractive power. Problems with abstraction mechanisms are usually caused by a lack of polymorphism. Smalltalk and Lisp are highly polymorphic. Next is Objective-C and Prolog. Then C++, and last is Modula-2. I considered defining polymorphism, but I don't have the time right now. If you really want to know, post the question. Someone will answer. Perhaps even me! -- Alan Lovejoy; alan@pdn; 813-530-2211; AT&T Paradyne: 8550 Ulmerton, Largo, FL. Disclaimer: I do not speak for AT&T Paradyne. They do not speak for me. _________________________Design Flaws Travel In Herds_________________________
mthome@bbn.com (Mike Thome) (04/19/89)
In article <5947@pdn.paradyne.com> alan@rnms1.paradyne.com (Alan Lovejoy) writes: >In article <2602@ssc-vax.UUCP> dmg@ssc-vax.UUCP (David Geary) writes: >>I would like to start a discussion concerning C++ and ool's. I would >>like to see comparisons of C++ vs. other object oriented languages such as: >>C++ vs. Lisp >> I'd like to know how C++ stacks up against the others as far as: Just to add to an otherwise complete (from my personal knowledge) synopsis of object oriented languages: I assume that the previous message's discussion of Lisp's "object orientedness" was based solely on the "defstruct" construct covered in CommonLisp The Language. It is certainly worth mentioning that a true object-oriented Lisp system has been accepted into the "official" CommonLisp set by the CL cleanup committee. I'll try covering a few of the original message's points with regards to CLOS (CommonLisp Object System), but a more complete discussion is available in a book by Sonya Keene entitled "Object Oriented Programming in CommonLisp" (or somesuch - Addison Wellesly, I believe)... >-- Portability -- >1) Language portability is a function of how similar the compilers for different >systems are and the breadth and depth of STANDARD functions that are provided >via STANDARD interfaces. This is largely an extra-linguistic issue that >has more to do with the history and culture of different language communities >than it has to do with the technical merits of languages as languages. >Smalltalk is the winner here, with C++ a strong runner-up. I'm not sure I see how this is *at all* a linguistic issue - it sounds as thought you are talking more of programming environment and fidelity of implementations than anything else. Frankly, I'm surprised that C++ is listed in the same sentence as Smalltalk in this regard - Smalltalk is an entire integrated environment implemented in itself... the only other similar systems that come close are Lisp Machines (from various vendors) running Flavors - perhaps some of the pascal P-machines might be grouped in the same way. >2) The other issue is how many different systems have implementations of your >language available. >C++ wins hands down on this point. Agreed. I would add that most machines that run commonlisp are also able to run at least one of the CLOS implementations (I know of at least two - PCL, which runs on just about any CL out there - certainly all the major vendors are covered, and TI has a native version (Symbolics has announced one as well, but it isn't expected for several months). PCL has the advantages that it is free (thanks to the good guys at Xerox) and easily portable. Native versions are faster). >-- Speed -- >Speed is just as much an implementation issue (compiler AND host CPU) as it is >a function of the language (syntax, semantics). Actually, I don't think >syntax has any effect on speed at all, unless the translation and execution >of the program are both being timed (e.g., an interpretive implementation). >The semantics of a language affect speed of execution in several ways: >... There is no such thing as a free lunch. I'll not itemize responses to this section: a summary of this whole issue is covered by that final line: Expressive power usually requires more machinery to support it - it is exactly the same issue as the Lisp/Smalltalk vs. C/ModulaII camps (which we will NOT go into here - suffice it to say it all depends on what you want to do and how you want to do it... and possibly what sort of hardware you want to do it on). This applies to CLOS vs. C++ just as well: C++ can be fast because much of the "object oriented"ness can be "compiled out" and requires little runtime support (not to be taken as other than praise - C++ does very well at furthering the "charter" of C). CLOS (for instance) must be able to deal with a far more complex (dynamic) runtime environment than C++, as well as such things as multiple class inheritance, multiple argument dispatch, etc. Even so, the better CLOS implementations pay surprisingly little cost over funcall. (BTW, some people in the object-oriented community have object to calling CLOS "object oriented" because it is not based on the usual message passing protocols - rather it uses the generic function metaphor). Some of the Lisp-running hardware is able to provide much better run-time support for CLOS than any conventional-architecture machine will be able to for C++ (or successors). Both Symbolics and TI have loadable microcode sets capable of implementing the basics as instructions. >-- Object Orientation -- >The definition of "object oriented language" is open to debate. Instead of >debating the minimum set of attributes that an object-oriented language >should have, it is more instructive to consider the ideal case. > First, some definitions: A class is a set of values and the functions/relations >defined on the members of that set. An object is an instance of a class which >represents one of the values in the set, that is, one of values of the class. > Inheritance is the ability to define a new class in terms of its differences >(extensions, deletions, changes) from some other pre-existing class. CLOS Generalizes that to "... from some other pre-existing (required for instance instantiation) class or classes". >The ideal object-oriented language would: >1) Have user-definable classes. CLOS satisfies this requirement - methods may be specified not only on defined classes, but also built-in data types (ie. integers vs. floats vs. complex vs. ratios ... etc) and even single values. >2) Have class inheritance. CLOS has this. In addition, it allows inheritance from multiple (possibly disjoint) classes. >3) Allow function/operator overloading. CLOS has this. Any function may be specialized on any one or more of its required arguments. (there is no difference between operator and function in lisp. Note that macros and special forms may not be specialized). >4) Be completely polymorphic. >Smalltalk and Lisp are highly polymorphic. Next is Objective-C and Prolog. >Then C++, and last is Modula-2. I would like to see the definition of "polymorphic" (for my own education). As mentioned somewhere above, CLOS has rejected the message sending/passing syntax of most OOL's in favor of generic dispatching (required by multiple argument dispatch): where in most OOLs, one might say something like "(send <object> :do-something-message <argument>)", you'd say "(do-something <object> <argument>)" in CLOS for equivalent functionality. In CLOS, however, you are allowed to specialize the behavior of a "message" to be based on any (one or more) of the arguments passed to the generic function. Anyway - I expect that your (informed!) choice of OOP Language will almost definitely follow your favorite philosophy of programming: if you are most productive in C, C++ is right for you... if LISP, than CLOS. Now, to close, I'll ask if anyone would like to comment on the seeming inconsistency of C evolving into a higher-level language (via C++)? At OOPSLA last summer, we were amazed to hear C++ people talking about adding garbage collection to the language! I'd hate to see what people think of as "C" turn into lisp-with-C-like-syntax. The big win of C is that it encorporates into a small language a number of very powerful abstractions with low (or zero) performance cost. Lets face it - if speed were all I cared about, I'd use Fortran exclusively... but I couldn't do without recursion for very long, so next choice is C. If I wanted limited OOP, I'd go for C++. Full dynamic environment? LISP. Full dynamic OOP? CLOS! Does anyone have an opinion as to how far up the "ladder of abstraction" C can be pushed without destroying its best features (low-level expression = speed)?
dan@acates.UUCP (Dan Ford) (04/20/89)
In article <2602@ssc-vax.UUCP> dmg@ssc-vax.UUCP (David Geary) writes: >I would like to see comparisons of C++ vs. other object oriented languages >such as: >C++ vs. Modula2 >C++ vs. Lisp >C++ vs. SmallTalk >C++ vs. Prolog >C++ vs. Objective C I would add to the list Eiffel -- see comp.lang.eiffel. Dan Ford uunet!acates!dan "You may not have stolen any eggs, but I get you've poached a few." Odd Bodkins
jima@hplsla.HP.COM (Jim Adcock) (04/21/89)
> Does anyone have an opinion as to how far up the "ladder of > abstraction" C can be pushed without destroying its best features > (low-level expression = speed)? So far C++ has done an extremely good job of avoiding adding overhead to low level expressions -- With a few small syntactic changes your favorite C code will compile under C++ and run as fast, and generate just as small executables. The slowness in coming up with a widely accepted memory manager for C++ is to find a scheme that will work in all C[++]-like applications -- including strict realtime applications. Still, memory management seems a necessity for larger OOP projects -- if only to debug and track down who isn't properly freeing their objects! A good, unobtrusive memory manager can also collect objects that are lost under unusual circumstances -- when an exception causes a loss of an environment for example. I see the limitations being the C-like syntax of C++. Will C-like syntax be acceptible for programming at a more and more "high level" -- or will the syntax become burdensome? But speed is not a problem.
gjditchfield@watmsg.waterloo.edu (Glen Ditchfield) (04/21/89)
In article <15425@bellcore.bellcore.com> sjs@ctt.bellcore.com (Stan Switzer) writes: >Adding garbage collection to C++, though, probably does more harm than >good. I do not see how to square garbage collection with the notion >of destructors, for instance. Remember, destructors aren't just for >memory management: a "window" destructor might "unmap" the window and >propogate "repaint" messages to previously obscured windows. I'd square garbage collection and destructors by having the collector invoke an object's destructor when it reclaims the object's storage. Perhaps destructors can help the collector out by breaking pointer cycles and setting pointers in the object's implementation to nil. Dr. Stroustrup's "Possible Directions for C++" paper in the 1987 Usenix C++ Workshop Proceedings distinguishes "primary objects", which should be garbage-collected, and "secondary objects", which are part of the imple- mentation of some other object and which can be easily managed by the other object's constructors and destructor. This is another way to reduce the cost of garbage collection. The paper mentions Jonathan Shopiro's "counted pointer" classes, which provide garbage collection for C++. Unfortunately the reference given is for a then-unwritten paper. Is there a better reference or a publically available implementation? Glen Ditchfield gjditchfield@violet.uwaterloo.ca Office: DC 2517 Dept. of Computer Science, U of Waterloo, Waterloo, Ontario, Canada, N2L 3G1 "... and the rest, we will spend foolishly!" -- _Svengali_
new@udel.EDU (Darren New) (04/22/89)
In article <282@acates.UUCP> dan@acates.UUCP (Dan Ford) writes: >In article <2602@ssc-vax.UUCP> dmg@ssc-vax.UUCP (David Geary) writes: >>I would like to see comparisons of C++ vs. other object oriented languages >>such as: >>C++ vs. Modula2 >> ... [deleted] >I would add to the list Eiffel -- see comp.lang.eiffel. > >Dan Ford uunet!acates!dan I would remove Modula-2 from the list. The only vaguely OO-like construct it has is exporting pointers to types that the user cannot access. This is like saying ANSI C is OO because you can cast (struct foo *) to (void *) and back again. Modula-2 has none of the OO advantages at all. -- Darren
john@linus.UUCP (John D. Burger) (04/22/89)
I've never used C++, but I've heard that C++ is not simply an extension to C, but is extra-C, in that the syntaxes are different. This is as opposed to CLOS and (again, I've heard) Objective-C. If this is indeed the case, then C++ can't be written in C, but requires preprocessing. CLOS is written in CommonLisp, which is one reason that it can be quite portable. This seems to me to be a minus for C++ from both an engineering and a human-factors point of view. John
kobryn@esosun.UUCP (Cris Kobryn) (04/25/89)
In article <1022@quintus.UUCP> ok@quintus.UUCP (Richard A. O'Keefe) writes: . . . >The ideal object-oriented language would: >1) Have user-definable classes. >Lisp and Prolog >permit the programmer to define his own class mechanism. There are versions >that come with classes built in. >Smalltalk and Lisp are highly polymorphic. Next is Objective-C and Prolog. >Then C++, and last is Modula-2. Look, will you _please_ take Prolog out of this discussion? Prolog is not an object-oriented language. It makes no pretence of being an object-oriented language. It goes out of its way NOT to be an object- oriented language. Consider C&M's intro sentence (Ch. 1) in "Programming in Prolog": Prolog is a computer programming language that is used for solving problems that involve *objects* and the *relationships* between objects.... Being paid by a Prolog company, I naturally think that Prolog is super-wonderful (logic is God and Warren is its prophet), but anyone who buys a Prolog system in the expectation that s/he will find it possible to define objects in it is in for a big disappointment. It is more than *possible* to define objects in Prolog. Consider Quintus' ProWINDOWS, an OOPS for UI devlopment: it supports abstraction, inheritance, polymorphism and message-passing. (If you need a technical POC at Quintus, I'd be glad to oblige ;->) -- Cris Kobryn
rai@wilbury.uucp (Nitin Rai) (04/26/89)
In article <461@esosun.UUCP> kobryn@esosun.UUCP (Cris Kobryn) writes: >It is more than *possible* to define objects in Prolog. Consider Quintus' >ProWINDOWS, an OOPS for UI devlopment: it supports abstraction, inheritance, >polymorphism and message-passing. (If you need a technical POC at Quintus, >I'd be glad to oblige ;->) > >-- Cris Kobryn No you are not defining objects in Prolog. ProWINDOWS is a separate process (C process) and you can create, manipulate and destroy "Objects" defined in ProWINDOWS through prolog. The objects are ProWINDOWS objects that accessible through prolog. It doesn't make Quintus Prolog object oriented in any way. Nitin { "If Prolog is god and Warren is its prophet, then O'Keefe is its messiah!:-) }