<<

What is Object-Oriented Programming9

Bjmne StMStNp,AT&T Bell Laboratories

Ohjedenkntedhas ot all programminglanguagescan duce ++and partly because C++is one of be object-oriented. Yet, claims the few languages that supports data ah become a buzzword have been made that APL, Ada, straction, object-oriented programming, that implies “good” Clu, C++,Iaops, and Smalltalk are object- and traditional programming techniques. proghmming But oriented languages. I have heard discus- I do not cover issues of concurrency and sions of object-oriented design in C, Pas- hardware support for specific,higher level when it comes to cal, Modula-2, and Chili. Could there language constructs. really supporting this somewhere be proponents of object- oriented programming in and Programming paradigms pardighm, not all Cobol? I think there must be. Object-oriented programming is a tech- lameesare equal. “Object-oriented” has become a high- nique - a paradigm for writing “good” tech synonym for “good.” Articles in the programs for a set of problems. If the term trade presscontain arguments that appear “object-oriented language” means any- to boil down to syllogisms like: thing, it must mean a language that has Ada is good; object-oriented is good; mechanisms that support the object- thert$oore, Ada is object+niated. oriented style of programming well. There is an important distinction here: This article presents my view ofwhat ob ject-oriented means in the context of a A language suppurtsa programming style if it provides facilities that make it con- general-purpose . venient (reasonably easy, safe, and efi- I present examples in C++,partly to intre cient) to use that style. A language does not support a technique if it takes excep An earlier version of this article appeared in /kr.Fmt tional effort or skill to write such pro- Etrmpnii G7$ on O~Prl-(~i~/k~~rntnr,lR.Spnnger- Verlag. NewYork. 1987.p~.51-70. grams; in that case, the language merely

10 0740-7459/88/05OO/OO10/$01 .OO 01988 IEEE IEEE Software wrcilhc prograinmcrs to use the techniqiie. that has found itsway into the compiler or ' Procedul-al programming uses frrnc- For examplc,you can wire structured pro- the literature. tions tv ci-catc oi-dcr in a maze of alp grains in Fortr;in and type-sccurc pro- , rithms. grams in C, and yo~ican use data ahstrac- Procedural. The original - arid pi-ob 1 tioii in Moclul>tZ, but it is iinnecessarily ably still the most cvnirnoii - program- Data hiding. Over the years, the empha- hard to do so because those languages do rning paradigm is: sis in the progi-am design has shifted from not .support those techniques. , procedure design to data organization. Dmdr rohirh prowilurrs you want: ILW lhr ~ Among ot~ici-things, this reflects an in- Support for a pidigin conics not only Imt iilgonlhms ym cnn,/ind. in the obvious foi-in of language facilities crc'ae in prograni size. '4set ofrelated pre that let you use the paradigm directly, bur The foC1l.S is on proccdnrc design -the ~ cedures and the data they manipulate is also in the niorc subtle forms of compilc- algorichtn needed to pelform the desired often called ii ~notlule.The programming tiin<=aiid runtime checks foi- uniiiten- computation. Iaiguages support this par- pal-adigniis: adigm with facilities for passing arguments tional deviations f'rom the paradigm. Type Zlrridr ~i~hi~hmoduIr.rycnL w(m~;pn?lzlion to fnnctions and retLlrningvalues checking, ambiguity detection, and run- theprop-(on ,si) thnt dntn is hiddm in functions. The literature about this para- time checks are an examples of linguistic 1 moduh. support for paradigms. Extralinguistic digin is filled with discussions of how to This paradigm is known the data-hid- facilities such as standard librarics and as ing principle. U%en procedures do not pi-ograinrningeinironments can also prw need to be grouped with related data, the \idr significant support for paradigms. A languee does not procedural style suffices. In fact, the tech- One language is not nccessarily better sumta fechique if niques for designing good procedures are than another because it a feature the has still applied, now to each procedure in a other does not - therc are many ex- it takes exceptional module. amples to the contrary. The impormiit emrt or skill to write The most coninion example ofdata hid- issue is not how many features a language such proglams. ing is a definition of :I stack module. A has, but that the features it docs have are good solution requires sufficient to support the desired program- a user interface for the stack (for ex- ming styles in the desired application pass arguments, how to distinguish differ- ample, thefLinctionspustl() and pop()), areas. Specifically, it is important that: ent kinds ofargumcnts and different kinds that the stack representation (for ex- of functions (procedures, routines, mac- All features are cleanly and elegantly ample, a vector of elements) can be ros, etc.),and so on. integrated into the language. accessed only through this user interface, Fortran is the original procedut al lan- It is possible to cornhilie features to and guage; Algold0,Algol-68, C, and Pascal are achieve solutions that would have other- that the stack is initialized before its later inventions in the same tradition. wise required extra, separate features. first use. An example of good procedural style is a There arc as few spurious arid special- A plausibly external interface for astack square-root function. Given an argument, pirposc features as possible. module is the function neatly produces a result. To Implementing a feature does not im- do so, it performs a well-understood math- ,(I declai-ation of tlic inteifare of module pose significant overhead on programs ematical computation. // stackol characters that do not require it. chai-pop(): A user need only know about the lan- void push (char): guage subset used explicitly to write a pro- double sqrt(doublc arg) const sr-nck-cife = 100; gram. I // the rode for calcdating a squarv 1-oot Assuming this interface is found in a file The last two principles can be suni- I called stark.h, the intemalscan bedefined marized as "what you don't know won't like this: hurt you." If. there are any doubts about void some-function () I #include "5utk.h" the usefulness ofa feature, it is better left double root2 = sqrt (2); static charv[stack-siie]: // "static" means out. It is much easier to add a feature to a // ... // local to this language than to remove or modifv one I // file/rnodule

May 1988 11 static char* p = v; // the stack is initially a type-manager module. Ifyouwanted two fined type.* The // empty stacks, you would define a stack-manager becomes: char pop() module with an interface like this: I Decide which types you want; plovide afull // check for underflow and pop // stack-id is a type; no details about set ofoperationsfor each type. I // stacks or stackjds are known here: void push (char c) class stack-id; When there isnoneedformore thatone I // make a stack and return its identifier: object of a type, the data-hiding program- // check for overflow and push stack-id create-stack(int size); ming style using modules suffices. Arith- I // call when stack is no longer needed: metic types such as rational and complex It is quite feasible to change this stack destroy-stack(stack-id); void push(stack-id, char); numbers are common examples of user- representation to a linked list. The user char pop(stack-id); defined types: does not have access to the representation This is certainly a great improvement class complex 1 anyway (because v and p were declared double re, im; static - that is, local to the file or module over the traditional unstructured mess, public: in which theyweredeclared). Such astack but "types" implemented this way are complex(doub1e , double i) { re=r; im=i; 1 can be used like this: clearly very different from the types built // float->complex conversion: into a language. complex(doub1e r) { re=r; im=O; 1 #include "stack.h" In most important aspects, a type friend complex operator+ void some-function() (complex, complex); I created through a module mechanism is // binary minus: chart= pop(push('c')); different from a built-in type and enjoys in- friend complex operator- if (c != 'c') error("impossib1e"); ferior support: Each type-manager mod- (complex, complex); I ule must define a separate mechanism for // unary minus: friend complex operator-(complex) ; creatingvariables of its type, there is noes As originallydefined, Pascal doesn't pro- friend complex operatort vide satisfactory facilities for such group tablished norm forassigningobject identi- (complex, complex); ing: The only way to hide a name from the fiers, a variable of such a type has no name friend complex operator/ (complex, complex); rest of the program is to make it local to a known to the compiler or programming environment, and such variables do not // ... procedure. This leads to strange proce- I dure nestings and overreliance on global obey the usual and argument-pass data. ing rules. The declaration of the complex class Cfaressomewhatbetter.Asshownin the For example: (the userdefined type) specifiesthe repre- example, you can define a module by sentation ofacomplexnumberand theset void f() of operations on a complex number. The grouping related function and data defini- I tions in a single source file. The program- stack-idsl; representation is @'vu& that is, re and im mer can then control which names are stack-id s2; are accessible only to the functions seen by the rest of the program (a name specified in the declaration of class com- SI = create-stack(200); plex. Such functions can be defined like can be seen by the rest of the program un- // Oops: forgot to create s2 lessit has been declared static). So in C you this: can achieve a degree of modularity. char c 1 = pop (s1 ,push (s1 ,'a')); complex operatoi-+ However, there is no generally accepted if (cl != 'c') error("impossib1e"); (complex al, complex a2) paradigm for using thisfacility, and relying I char c2 = pop(s2,push(s2,'a')); return complex on staticdeclarations is rather low-level. if (c2 != 'c') error("impossih1e"); (a1 .reta2.re,al.inita2.im); One of Pascal's successors, Modula-2, t goesa bit further. It formalizes the module destroy(s2); concept by making it a fundamental con- // Oops: forgot to destroy SI and used like this: I struct with welldefined module declara- complex a = 2.3; tions, explicit control of the scope of In other words, the module concept that complex h = I /a; names (import/export facilities), a mod- supports the data-hiding paradigm ena- complex c = a+b*complex(1,2.3); ule-initialization mechanism, and a set of blesdataabstraction, but doesnot support // ... c = -(a/h)t2; generally known, accepted usage styles. it. In other words, C enables the decom- Most, but not all, modules are better ex- position of a program into modules, while Abstract data types. Languages such as Modula-2 supports it. Ada, Clu, and C++ attack this problem by *As Doug Mcllroy has raid, 'Those typrs are not 'ab stract,' the) arc a real as rnrand/7mf."Anotherdefini- letting the user define types that behave in lion ofabsuact data types would requirr a mathrmatical Data abstraction. Programming with (nearly) the same way as built-in types. "abstract"sprcification of all ppes (both builr-in and iiserdcfinrd).What is referred to as typc's in this ai-tick modules leads to the centralization of all Such a type is often called an abstract data would. given such a specification. hr coticrete specifica- data of a certain type under the control of type, although I prefer to call it a userde- tions of such triilv abstrncr rntities.

12 IEEE Software pressed as userdefined types. When the such as draw() know about all the kinds of write gencral functions to manipulate programmer prefers to use a module rep shapes there are. Therefore, the code for shapes: resentation, even when a proper Facility any such function must by modified each wid rotatc-all for defining types is available, he can de- time a new shape is added to the system. (shape* v, iiit siic. iiit mgle) clare a type that has only a single object of If you define a new shape, every opera- // rotiitr all nicmlwrs of \ectoI “v”olaiie that t)pe. Alternatively, a language might tion on a shape must be examined and // “sire”“mglr” dcgrrrs pi-ovidc a module concept in addition to (possibly)modified. You cannot add a new I foi- (int i = 0: i < sile; i++) and distinct from the class concept. shape to a system unlessyou have access to v[i].rotatr(;ingle); the source code for every operation. Be- ~rohIP7mti userdefined type defines a cause adding a new shape involves touch- sort of black box. Once it has been de- ing the code of every important operation To define a particular shape, you must find, it does not really interact with the on shapes, it can require great skill and say that it is a shape and spccify its particu- rest ofthe program. The onlywav to adapt may introduce bugs into the code that lar properties: it to new uses is to modify its definition. handles the older shapes. clas5 cii-cle : public sh‘tpr { This is often too inflexible. Also, your choice of how you represent int radius: Consider defining a type shapfOr use in particular shapes can be severely cramped public: voiddraw() ! /* ... */ I; agraphics system.Asume for the moment by the requirement that at least some of that the system has to support circles, trian- their representation fit into the typically gles, and squares. Assunie also that you fixed-sized framework presented by the t; have some classes: definition ofthe general type shape The problem is that there is no distinc- InC++,thecircleclassissaid tobc dm’wd class point! /* ... */ 1; from the shape class, and the shapc class is class colol-j /* ... */ 1; tion between the general properties ofany shape (ashape hasacolor,itcan bedrawn, said to be a hatrofthe circle class. Anothel- terminolop calls circle a subclass and You might define a shape like this: etc.) and the propertiesof a specific shape (a circle is a shape that has a radius, is shape a superclass. eniiin kind ! circle, triangle, square 1; The programming pai-adiginis: drawn by a circle-drawiiig function, etc.). class shapc ! 1)mridr wliicli cimsrc you 71inni; /)ro71i& (1 point tenter; Object-oriented programming. The pill srt (iJ oprm~ionsJm-rtzrh rhss; wu~kr color- col: ability to express this distinction and take co~nrnoncilztyrxplitit using in1~m“lancP kind k; advantage of it defines object-oriented // representation ofshape Where tlierc is no such comrnoriality, programming. A language with constructs public: data abstraction suffices. I {ow much types point where() 1-rtiirii trnter; that let you express and use this distinction have in common so that the conimonality Loid movr(poiiit to) ! trtitri- = to; draw(); supports object-oriented pi-ogramming. can be exploitcd using inhet-itanceand \4r- t Other languages don’t. void draw ( ) ; tual fhctionsis the liunus test ofthe appli- 1 oid rotate(int) : The Simula inheritance mechanism cability ofot?jcct~)ricntedprogi-animing, // inorr operations provides asolution. First, you specify a class In sonic areas, such as interactive graph- I: that defines the general properties of all ics, there is clearly enormous opportunity The t)pr field. k, is used by operations shapes: for- object-orirntcd programming. In such a5 draw() and rotate() to determine clas shape ! other areas, such as classical arithmetic what shapr they are dealing with (in a Pas- point center; types and the computations based on cal-like language, you might use a variant color col; them, there appears to be hardly any need record with tag k). The function draw() // ... for more than data abstraction.* public: might be defined like this: point where() j setui-ii center; } Finding cornrnonalit)~among types in a void movr(point to) { trnte1- = to; draw(): system is not ii trivial proccss. How much wid shapc,::drau () I commonalit! can be exploited depends ! vii-tualvoiddraw(); switch (k) j on how the system is dcsigncti. (:on- vii-tual void Iot;itc( int); c-ax (ii-clc: monality inlist be actively sought when the // ... // draw ii cirrlc. system is drsignrd, borh by drsigning break; 1; as case triangle: classes specifically building blocks for // draw a trianglr The functions marked klirtual are those other typesatid bycxaminingclassrstosee bsrak; for which the calling interface can be de- if they have similarities that can be ex- caw sqiiarc: fined, but the implementation cannot be ploited in a common base class. // drawa sqiia~-e defined except for a specific shape. (‘Vir- I tual” is the Simula and [:++ term for “may ~ ~- 1 *Howr\cl. morr .id\anrcd m.ilhriiiatic \ iiiin bcnrlit be redefined later in a class derived from This is a mess. It requires that functions this one.”) Given this definition, we can

May 1988 13 Nygaard' and Kerr' explain what object- -vector(); // destructor ment andinitialization. Assignment might oriented programming is without re- int& operator[] (int index); // subscript be defined like this: // operator course to specific language constructs; t; vector::operator=(vector& a) Cargill has written a case study in object- // check size and copy elements oriented pr0gramming.l The vectorconstructorcan be defined to al- I locate space like this: if (sz != a.s/;) Supporting error("badvector six for ="); data vec tor::vector (in t s) for (inti = 0; i(&);// only members vector v; control copy operations. Consider the vec- // don't use v here // of x can v.init( IO); tor class: X(X&); // copy an X // use v here ... vectorvl(100); public: vector v2 = vl ; // make a new vector v2 This iserror-prone and inelegant. Abetter ... // initialized to VI I; solution is to allow the designer of a type to VI =v2; //assignv2tovl provide a distinguished function to do the Add does not support constructors, de- initialization. Such a function makes all* It must be possible to define the meaning structors, assignment overloading, or cation and initialization of a variable a of the initialization of v2 and its assign- userdefined control of argument passing single operation (often called instantia- ment to VI. It should also be possible to and function return. This lack of support tion) insteadoftwooperations. Suchan in- prohibit such copy operations; preferably stantiation function is often called a con- both alternatives should be available. For severely limits the class of types that can be defined and forces the programmer back structor. example: to data-hiding techniques: The user must In caseswhere constructingobject types class vector 1 isnontrivial,itisoften necessarytoprovide design and use type-manager modules in- int* v; stead of proper types. a complementary operation to clean up int SL; objects after their last use. In C++, a public: cleanup function is called a destructor. // ... Parameterized types. Why would you void operator=(vector&);// assignment Consider a vectortype: want todefine avectorofintegersanyway? vector(vector&); // initialization I; Typically, a user needsavector ofelements class vector { of some type unknown to the writer of the int sz; //number ofelements int* v; // pointer to integers type urctor. Consequendy the vector type public: specifies that user-defined operations ought to be expressed so it takes the ele- vector(int); // constructor should be used to interpret vector assign- ment type as an argument:

14 IEEE Software clas vcctor { vectors of a type for which < was not de- it (04 I1 s/<=i) iaiw \ccroI-ratigc; // vrrtoi- of elements of type 1 fined, as long as the vector-sorting opera- wtiiini v[ i] : T* v; tion was not actually invoked. I int sr; public: A problem with parameterized types is This will cause thr call stack to be 1111- vcrtor(int sj that each instantiationcreatesan indepen- raveled until an cxception hmdlcr for UP<- { dent type. For example, the type upr- tor-rctng-pis found and executed. if (s <= 0) error("hadvector sire"); tor is unrelated to the type uer- An exccption handlet- rnay he definrd v= newT[sr=s]: //allocateanarray tor.Ideally you would like to be for a specific block: I able to express and use the commonality T&operator[] (inti); of types generated from the same paranie- void E( j { int sire() { retur-n s/; 1 terized type. For example, both uer- veCtOl-v( IO); // ... torhave a size() ci-rors hei-c ;ire tiandlrtl 1; function that is independent of the pa- by the local cxceprioii handler tielined lxiow Vectors of specific types can now be de- rameter type. It is possible, but not easy, to // ... fined and used: deduce this from the definition of class vector and then let size() be applied to any vrctor-v2(200);// v2is avector guage that supports both parameterized I rxccpc 1 // of 200 complex types and inheritance has an advantage //numbers \'er toir:vcc to i--ntigr : here. eri-or("f (): vector miigc VI-I-01"): v2[i] =complex(vl[xl,vl[)I): rerwn: Ada and Clu support parameterized types. Exception handling. As programs grow, I // cIIoI\ l1eI-e ii1-t' ll;llldlcd by the Unfortunately, does not; the notation and especially when libraries are used ex- C++ // globnl exception h;uidlci used here is still experimental. When they tensively, standardsfor handling errors (or // defined in vec.toi- are needed, parameterized classes are "exceptional circumstances") become ini- inti = g( ); // g niiglir c;trisc a rangr faked with macros. There need not be any portant. // error rising sonic vector // potenrial range vi-roi- runtime overheads compared with a class Ada, Algol48, and Clu each support a v[i] = 7: where all types involved are specified standard way to handle exceptions. Unfor- I directly. tunately, C++ does not. When necessary, There are many ways to define exceptions Typically, a parameterired type will have exceptions are faked using pointers to arid the behaiior of exception handlers. to depend on at least some aspect of a type functions, exception objects, error states, The facilit) sketched here resembles the parameter. For example, some of the vec- and the C library's signal and longjmp ones found in Modula-2+.This style of.ex- tor operations must assume that assign- facilities. This is not satisfactory because it ception handling can be iinplrrnented so ment is defined for objects of the parame- fails to provide even a standard framework that code is not executed unless iin excep ter type. How can you ensure that? One for error handling. tion is raised (except possibly for some in- way is to require that the designer of the Consider the vector example again. itialiration code). It can also be ported parameterized class state the dependency. What should be done when an out-of- across most <; iiriplernentations by using For example, "T must be a type for which = rangeindexvalueispassed to thesubscript setjmp() and longjmp() (sec the <;library is defined." A better way is not to require operator?The designer of the vector class manual for your system). this -or to take a specification of an argu- should be able to provide a default be- Could exceptions, as defined above, be ment type as a partial specification. Acom- havior for this: completely faked in a language such as pilercan detectifaamissingoperationhas C++? Unfortunately, no. The snag is that class vector been applied and give an error message when an exception occurs, the runtime such as except vector-range { stack must be iinravclcd up to a point // define an exception called where an exception handler is defined. To cannot define // vector-range aid specifv default do this properly in <:++ involves invoking vrcto~-::operator[](non-copy&): // code for handling it destructors defined in the scopes in- vpe non-copy does not have operator= error("g1obal: vector range error"); exit (99); volved. This is not done by a <; longjmp() This technique letsyoudefine typeswhere I and cannot in general be done by the user. the dependency on attributes ofaparame- I ter type is handled at the level of the in- Instead of calling an error function, uer- Coercions. U ser-de fi ti ed coc rc io n s , dividual operation of the type. For ex- tor::operatm[]() can invoke the exception- such as the one from floating-point num- ample, you might define a vector with a handling code: bers to complex numbers implied by the sort operation. The sort operation might constructor comnjhx(doubk), have proven int&vector::operator[] (inti) use <, ==, and = on objects of the parame- unexpectedly useful in C++. Such coer- l ter bpe. Itwould still be possible to define cions can be applied explicitly or the prw

May 1988 15 grammer can rely on the compiler to add user-defined type. Given a sufficiently Then the iteration can be performed like them implicitly where necessary and un- powerful mechanism for defining new this: ambiguous: types and the ability to overload operators, vector v( sz); this can be handled without a separate inti; complex a = complex( I); mechanism for defining control struc- while (i=v.next()) print (i) ; complex h = I; // implicit: // 1 ->complex( I) tures. This solution is not as general as the itera- a = btcomplex(2); For a vector, defining an iterator is not tor solution, but it avoids overhead in the a = h+2; // implicit: necessary because an ordering is available important special case where only one // 2-> complex(2) to a user through the indices. I’ll define kind of iteration is needed and where only Coercions were introduced into C++ be- one anyway, to demonstrate the tech- one iteration at a time is needed for avec- nique. cause mixed-mode arithmetic is the norm tor. in languages for numerical work and be- There are several iterator styles. My If necessary, you can apply a more cause most userdefined types used for cal- favorite relies on overloading the function general solution in addition to this simple culation (of matrices, character strings, application operator ():* one. The simple solution requires more and machine addresses) have natural class vector-iterator [ foresight from the designer of the con- mappings to and from other types. vector&v; tainer class than does the iterator solution. One use of coercions has proven espe- inti; The iterator-type technique can also be cially useful in organizing programs: public: vector-iterator(vector&r) { i = 0; v = r; ) used to define iterators that can be bound complex a = 2; intoperator() () to several different container types, thus complex h = a+2; // interpreted as { return i

16 IEEE Software liinction semantics. This optitiii/;itioii is equally valuable as a support f0r data ab straction. 2. \'irtual fiinction call: The fiuiction Supporting called depends on the object t)pe, ivhich dojectaiented usually cannot be determined until i-iiii- time. Typically, the pointer p will he of programming some base class Band the object \\ill be an The lmsic support functions a prograin- object of some derived class I). The call met- needs to Lvrite otijcct-oriciitc.tI pi-tr mechanism must look into the object and grains arc a class iriechxiism ivith iiilieri- find some infijrmatioti placed there by the tancc and a inech;iiiisni that lets calls of compiler to determine which function /is member fiinctions depend the actual on to he called. Once ilia function, say 11::L is object t)-pe (\\-lien the actual type is uri- found, it is called iththe mechaniwi tle- kno\\m at coinpile time). sciitied above. At cornpile time, the name The design of the iiieinl,er-f~inctioiicall- /is converted into an index to a table con- ing rnechanism is critical. In atltiitioii. taining pointers to fiinctions. This \ii-tiial- 1'. .'I' ' 'IC I it ics I hat siipport data-ahstraction call mechanism can essentially be rnatle as techniques arc important liecause the ar- efficient as the normal fiinction<.all incch- giiiiieiits 101-(lata ahstraction and for its I-e- anisrn. In the standard (;++ irnple- finrincnts to use types elegantly are men tat ion, only five additional 111em~)ry equal1y wlid \vh ere sup )rt foi- o tije c t- p( references are used. In cases where the ac- oriented progi-animiiig is available. tual type can be deduced at compile time, The sticccss of Imth techniques hinges even this overhead iseliminated and in-lin- on thedesi~rioft~peaantionthrrasr,flex- ing can be used. Such cases are quite com- ibility, and efficiency of such t\pcs. object- mon arid important. oriented programming simply lets user- In languagesmith wwkstxic type chc~k- defined t)'pes be far more flexible and ing, a third, more elaborate alternative gcncral than the ones designed using only must be used. In ;I languagr like Smalltalk, data-abstraction techniques. a list of the names of;111 ineiiibei. fiiiictions (callrd methods) of a class are stor-rrl so Calling mechanisms. The key laiiguage the! can be found at runtime: facility to support object-oi-ienterl pro- 3. Method invocation: The appropriate grarniiiing is the rnechanism by which a table of method iiarnes is first foiind bp ex- member fiinction is invoked for an object. amining the object that ppoints to. 111 this Foi- example, gi\en pointer p, how is ii call table (or set oftables),the stringjis looked /e/(arg handled? There is a range of up to seeiftheot~jccthasan~).Ifan/() is choices. found, it is called; othenvise, some error In languages such as (:++ ;ind Simrila, handling takes place. This lookup differs whcr-e static type checking is used cxtcii- from the lookup done at compile tinir in a sivcly, the type system can select bet\veen statically checked language because the different c;illing mechanisms. In (:++, method invocation uses a method table for there are two alternatives: the actual object. 1. Normal function (AI: The member A method invocation is inefficient com- function to call is determined at compile pared with a virtual function call, but it is time (through a lookup in the coinpilet-'s more flexible. Since static type checking of symbol tables) and called with the stan- arguments qpically cannot be done for a dard functioncall niechanism, with an ar- method invocation, the use of rnerhods gument added to identify the object for must be supported by dynamic type check- which the function is called. Mhn the ing. standard function call is not efficient enough, the programmer can declare a Type checking. The shape example car- fiinction to be in-line and the cornpilrr-bill lier showed the power oftirtiial functioiis. try to expand its body in-line. This lets you What else does a mcthod-invoc;irion achieve the efliciency of ;I macro expaii- mechanism do for you? It lets you invoke ), = cs.,,(,,,( 1: sion without compromising the standard any method for any object. p->t;ll\eoff (i:

May 1988 17 The use of static type checkingand virtual sort to using type fields to determine ac- // my stuff function calls leads to a somewhat differ- tual types of objects, so the problems with 1; ent style of programming than does dy- the code’s lack of modularity would re- class my-displayed namic type checking and method invoca- main.* :public displayed { // not a task tion. For example, a Simula or C++ class This implies that class derivation (sub // my stuff specifiesa fixed interface to a set of objects classing) is an important programming t; (of any derived class), while a Smalltalk tool in its own right. While it can be used to With single inheritance, only two of these class specifies an initial set of operations support object-oriented programming, it three choices are open to the program- for objects (of any subclass). In other has wider uses. This is particularly true if mer. This leads to code replication or loss words, a Smalltalk class is a minimal speci- you associate inheritance in object- of flexibility- and typically both. In C++, fication and the user is free to try opera- oriented programming with the idea that this example can be handled with no sig- tions not specified, while a C++ class is an a base class expresses a general concept of nificant overhead (in time or space),com- exact specification and only operations which all derived classes are specializa- pared to single inheritance, and without specified in the class declaration are tions. This idea captures only part of the sacrificing static type checking.’ guaranteed to be accepted by the com- expressive power of inheritance, but it is Ambiguities are detected at compile piler. strongly encouraged by languages where time: every member function is virtual (or a classA(public:f();... 1; Inheritance. Consider a language that method). class B public: f();. . . I; has some form of method lookup without Given suitable controls over what is in- class C : public A, public B { .. . I; an inheritance mechanism. Does that lan- herited,” class derivation can be a power- ful tool for creating new types. Given a voidgo I guage support object-oriented program- C* p; ming? I think not. class, derivation can be used to add and p>f();//error: ambiguous subtract features. The relation of the re- t Clearly, you could do interesting things sulting class to its base cannot always be In this capability,C++ differs from the ob with the method table to adapt the objects’ completely described in terms of speciali- ject-oriented Lisp dialects that support behavior to suit conditions. However, to zation; factoring is a better term. multiple inheritance. In these Lisp dia- avoid chaos there must be some systematic Derivation is another programmer’s lects, ambiguities are resolved by consider- way to associate methods and the data tool and there is no foolproof way to pre- ing the order of declarations significant, structures they assume for their object rep dict how it is going to be used - and it is by considering objects of the same name resentation. To let a object’s user know too early (even after 20years ofsirnula) to in different base classes identical, or by what kind of behavior to expect, there tell which uses are simply misuses. would also have to be some standardway to combining methods of the same name in base classes into a more complex method express what is common to the different Multiple inheritance. When class A is a of the highest class. behaviors the object might adopt. Thissys- base of class B, B inherits the attributes of In C++, you would typically resolve the tematic, standard way is an inheritance A; that is, B is an A in addition to whatever ambiguity by adding a function: mechanism. else it might be. Given this explanation, it Consider a language that has an inheri- seems obvious that it might be useful to class C : public A, public B 1 tance mechanism without virtual func- have class B inherit from two base classes, public: AI and This is called multiple inheri- f() tions or methods. Does that language sup A2. 1 port object-oriented programming? I tance.* // C’s own stuff think not: The shape example does not An example of multiple inheritance are A::f(); have agood solution in such a language. two library classes, the displayed class and B::f(); the task class, that respectively represent I However, such a language would be ... more powerful than a plain data-abstrac- objects under the control of a display I tion language. This contention is sup- manager and coroutines under the con- ported by the observation that many trol of a scheduler. A programmer could In addition to this fairly straightforward Simula and C++ programs are structured then create classes such as concept of independent, multiple inheri- using class hierarchies without virtual tance, there appears to be a need for a class my-displayed-task more general mechanism to express de- functions. The ability to express com- : public displayed, public task monality (factoring) is an extremely // my stuff pendencies between classes in a multiple- powerful tool. For example, the problems I; inheritance lattice. In C++, the require- associated with the need to have a com- ment that a subobject be shared in a class class my-task object is expressed through the mecha- mon representation of all shapes could be : public task { // not displayed solved; no union would be needed. nism of a virtual base class:

However, in the absence of virtual func- *This is the problem with Sirnula’s Inspect s~teinem class U‘ , , . 1; tions, the programmer would have to re- and the reason it does not have a counterpart in C++. class Bwindow // window with border

18 IEEE Software : piihlit \ii tual \I Here is an example that demonstrates programming cnvii-oniiicnt. 1’;ii-t of the j ... t: part of the range of choices for encapsula- reason is that objcct+rientcd pl-ogram- tion in C++: ming builds on rhc language iinpro\v class .Ilivindow 1 ’ \vindowwith mriiii nients all-ead! pi-o\ided to support data : puhlic 1irtual \V class B 1 I ... t: // class members are abstraction, so 1-elativelyfkw additions arc // default private needed. cl;t5s I%.Il\V wiiido\\ with bordrr int il; This assume’ that an ol~jcct-oi.icnted I/ allti lllellll void fl (): : puhlic B~indow,puhlit 4lwiiidow protected: language docs indeed suppor-t data ab- I ... 1: int i2: StrdctiOll. HC)l.iC\Cr, the SUrIpOrt for data r.oidfL(); abstraction i+ oftcn deficiclir in airch Iaii- Here, the single window siibobjcct is public: guages. Conversely, languages that sup ?hared bv the Rwindow and Bwindow sib int i3; port dara abstraction a1.c typic;llly defi- objects of a RMM’. The Lisp dialects use void f3 (); citnt in their support of’ object-oriented mrthod combinations to ease program- friend void g(B*): //any function can bc //designated as a friend programming. ming using such complicated class hierar- 1; chies. C++ docs not. Object-oiiented programming further Private and protected members are not blurs the distinction between a program- Encapsulation.( :oilsider a class member generally accessible: ming langiiagt. and its en\ir-onnicnt. Bc- (data or function) that must be protected cause more powerful special- and gencl-al- void 11 (B* p) from unauthorized access. M’hat choices purpose user-defined types call be de- I are I-easonahlc to deliniit the set of func- p>fl (); // error: B::fl is privatr fined, the! pei7ade user programs. This tions that inay access that member? p>f2()://error: B::f? is protected requires furthei- development of the ruii- //fine: B::fl is public The obvious aiisver for a language p>n(); time system, library Facilities, dchuggrrs, I supporting object-oriented programming performance measuring, monitoring is “all operations defined for this object,” Protected, but not private, members are tools, and so on. Ideally, tticsc ai-c inte- or all inember fiinctions. A hidden impli- accessible to members of a derived class: grated into a unified pi-ogi.aniniing e11- cation ofthisans~\cristhattherecannotbe Lironment, of which Smalltiilk is the best class D : public B 1 example. a complete and final list of all functions public: that may access the protected member voidg() Limits to perfection can since you alivays add another by deriv- I To claim to be general-purpose, a lan- ing a new class from the protected niern- fl (); // error: B::fl is private guage that is designed to exploit the tcch- her’s class and then defining a member fZ(): //fine: B::E isprotected, // but D is derived from B niques of data hiding, data abstraction, function of that derived class. This ap- f3(): //fine: B::fl ispublic and objectfl (); // fine: B::f.l is private. langiragc supporting data abstraction is // butgo isafriendofB This means that facilities must be avail- different: “1,ist the functions that need p>f2();//fine: B::n is protected, able for effectkc nuincl-ical work (float- ;icccss in the class declaration.” There is // birtg() isafrieiidofB ing-point arithmetic without over-head nothing special about these functions; p>t3(); //fine: B::tl is public that Would mike For-tran attr-active),and I thcy need not be member functions. nicino~milst be accessible so that dcricc X noninenit)ci- function with access to The importance of encapsulation issues drivers @an hc written. It must also he pi-ivate class members is called aJnmd in increases dramatically as program sire in- possible to write calla that conform to the (:++. Class Complex, above, \vas defined creases, and as the number and geo- (oftcn rather strange) standards required using friend functions. It is sometimes im- graphical dispersion of its users expands. for operating-sptcm intcrf‘accs. In addi- portant that a function may be specified as For a detailed discussion of encapsulation tion, it should be possible to call fiinctions a friend in more than one class. HaLing the issues, see SnydeP and Stroustrup.’ written in other languages fr-om it objcc-t- full list of.nicnibcrs and friends available is oriented language and for functions writ- a great ad~antagcwhen you are tr!ing to Implementation issues. Support for ob ten in the objcct<)ricntcd language to he undcrstand the bchaiior of a type and ject-oriented programming is provided called from a program lvrittrn ili another especially when you want to modify it. primarily by the runtime system and the language.

May 1988 19 It also means that an object-riented lan- critical areas while retaining control of bject-oriented programming is guage cannot rely completely on mecha- storage use in areawhere it matters. As an programming using inheritance. nisms that cannot be efficiently imple- alternative, it is feasible to have a language 0Data abstraction is programming mented on a traditional architecture and without garbage collection and then prtr using userdefined types. With few excep still expect to be used as ageneral-purpose vide sufficient expressive power to enable tions, object-riented programming can language. A very general implementation the design of types that maintain their own and ought to be a superset of data abstrar- of method invocation can be a liability un- storage. C++ is an example of this. tion. less there are alternative ivavs of request- Exception handling and concurrency ing a service. These techniques need proper lan- are other potential problems. Any feature Similarly, garbage collection can be- guage support to be effective. Data ab- that is best implemented with help from a come a performance and portability bot- straction needs support primarily in lan- linker is likely to become a portability guage features; object-oriented tleneck. Most object-oriented program- problem. ming languages use garbage collection to programming needs more support in the simplify the programmer’s task and to re- The alternative to having low-level fea- programming environment. To be con- duce the complexity of the language and tures in a language is to handle major ap sidered general-purpose, a language must its compiler. However, it ought LO be plication areas using separate low-level let you use traditional hardware effec- possible to use garbage collection in non- languages. tively. .:. Acknowledri!ments I~ References An earlier version of this article was presented to the Association 1. K Nygaard, “Basic Concept, in Object-Oriented Programming,” of Sirnula Users meeting in Stockholm in August 1986. The discus- SIGPhn ,%firm, Oct. 1986, pp. 128-132. sions there caused many improvements in both style and content. 2. R. Kerr, “Object-BasedProgramming: A Foundation for Reliable Bi-ian Kernighan and Ravi Sethi made many constructive com- Softwa-e,”I%c.14th Simulu C!sm ‘(;(in$, Sirnula Inlonnation, Oslo, ments. Also, thanks to all who helped shape Ctt. Norway, 1986, pp. 159.165; a short version is “A MaterialisticView of the Sofmare ‘Engineering’ Analog); SIGJ’kn Notzm, March 1987, pp 123-125. 3. T. Cargill, “IPI: A Case Study in ObjectQi-ietlted Programming,” SIGPhn Nofires, Nov. 1986, pp. 350-360. AN OUTSTANDING SEMINAR BY 4. B. Liskov et al., “Abstraction Mechanisms in Clu,” Cnmm. ACM, THE IN TERNATIONALLY RECOGNIZED AUTHORITY ON ... Aug. 1977, pp. 564-576. 5. J,Shopiro, “Extending the Ctt Task Systciii IoIReal-Time Appli- cations,”13ur. (5mzx C++ Wcnkshvp, Cseiiix, Santa Monica, Calif., Software Cost Estimation Using 1987. pp. 77-94. 6. A. Snyder, “Encapsulation and Inhrritmce ill Object-0rienIed Programming Iaiguages,”SlGf’kin Notzrr.\, Nov. 1986, pp. 3845. 7. B. Su-oiistrup, 7hr C++ Programming ImpiagP3 Addismi-Wesley, - - ~-~ - COCOMO- - Reading, Mass., 1986. (Constructive Cost Model) 8. D. Weinreb aid D. Moon, lisp Mnrhinr Mrinual, Synbolics, Cam- bridge, Mass., 1981. 9. B. Stroustrup, “Multiple Inheritance for Ctt,” I’m. Spring Special Feature: A Full Description of the b.’urnpmn (’nix Ckrs Croup Con{, EEUG, 1,ondon. 19x7. Recently Developed Ada COCOMO Model

COCOMO vs Other Cost Modelsfrechniques Basic. Intermediate, Detailed COCOMO- FeaturedApplications Tailoring COCOMO COCOMO Extensions-Incremental Development, Acquisition management

PRESENTED BY: Bjarne Stroustrup is the designer-and original implemen terof Ctt. His research interests include distributed systems. operating sys- DR. BARRY W. BOEHM tems, simulation, programming methodology, and programming languages. LOS ANGELES WASHINGTON, DC Stroustrup received an MS in mathematics and computer science June 9-10, 1988 June 13-14, 1988 from the University of-Aarhus and a PhI) in coniputer science from Cambridge University. He is a distinguisehd niemhei- of the Coin- puter Science Research Center and is a member of IEEE and ACM. For Information Call: (213) 5M.4871 Address questions about this ai-tick to the anthol- at AT&T Bell Laboratories, fin, 2(:-324, 600 Mountain Avr., Mui-ray Hill, N J 07974. Reader Service Number 4 IEEE Sottware