home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR9 / A9X_0610.ZIP / 9X&CPLUS.HLP < prev    next >
Text File  |  1993-06-10  |  29KB  |  507 lines

  1. Form S100-1092a
  2. 9X&CPLUS.HLP
  3.  
  4. Ada Information Clearinghouse, 1-800-AdaIC-11, 703/685-1477
  5.  
  6.                         CONTRASTS: Ada 9X and C++
  7.  
  8.                              Edmond Schonberg
  9.                              NYUAda 9X Project
  10.                             New York University
  11.                              251 Mercer Street
  12.                             New York, NY 10012
  13.                            Schonberg@cs.nyu.edu
  14.  
  15.                                April 22, 1992
  16.  
  17.                               1. Introduction
  18.  
  19. Ada 9X and C++ are modern general-purpose languages of roughly similar power, 
  20. aimed broadly at the area of Systems programming.  Ada 9X, like Ada, is also 
  21. intended for embedded and real-time systems, and has a number of built-in 
  22. features to support concurrent and distributed programming.
  23.  
  24. Both Ada 9X and C++ have features that modern software engineering practice 
  25. considers indispensable: modularity, information hiding, structuring tools for 
  26. large programs, inheritance and support of object-oriented design methods, 
  27. various mechanisms for parametrizing software components, etc.  Both languages 
  28. are clearly superior to their competitors (C, Modula-2 Pascal, Eiffel) in 
  29. terms of expressive power, maturity, and software base.  Ada is also superior 
  30. to these in terms of safety and reliability.
  31.  
  32. We will show that Ada 9X has similar advantages over C++, in particular when 
  33. software costs are examined over the lifetime of the software system.  Rather 
  34. than being comprehensive, we choose to focus on details where the philosophies 
  35. of both languages are in sharpest contrast.  We will often use Ada rather than 
  36. Ada 9X in the discussion, because many of the best features of Ada 9X are 
  37. simply inherited from its parent.
  38.  
  39.                2. Anything you can do, I can do as well
  40.  
  41. The comparison of programming languages is in part a subjective affair; 
  42. judgements are influenced by personal stylistic choices, by familiarity, by 
  43. the well known first-language effect, etc.  Given that all programming 
  44. languages in use are Turing-equivalent, no claim can be made as to the 
  45. absolute advantage of one over the other.  Rather, the arguments have to be 
  46. pragmatic ones: reliability, ease of use, and modifiability of the resulting 
  47. software.  Social considerations are also relevant: the programming culture, 
  48. the training of programmers, the availability of tools, the mechanisms by 
  49. which programming idioms circulate through the community, etc.
  50.  
  51. For example, consider the question of library management, a vital issue in 
  52. every sizable project.  The integrity of an Ada system is protected first by 
  53. the library mechanism, whose definition is an integral part of the language.  
  54. Every large project will build on top of the library management some 
  55. configuration control machinery which simplifies the coordination of the work 
  56. of many programmers, but the first guarantee of reliability is that the Ada 
  57. system itself will not let you build a system with out-of-date components.
  58.  
  59. The C++ programmer (or the C programmer for that matter) will claim that he 
  60. obtains the same effect by the use of the Make utility and by the disciplined 
  61. naming conventions of the header files.  This is true, but the point I want to 
  62. make is that to replicate the mechanisms that Ada supplies takes more than 
  63. C++: it requires a number of utilities and tools that are common in the Unix 
  64. environment, but are in no way standardized and are not part of the language.  
  65. Thus there are no semantic checks on their use, and no relationship between 
  66. these tools and the language translator itself.  C and C++ depend critically 
  67. on their environment.  This has two consequences:
  68.  
  69. 1.  When judging the size of the language (as in the frequent complaint: "Ada 
  70. is too big") one must consider that competent use of C++ requires much more 
  71. knowledge than just the language; it requires comparable familiarity with a 
  72. number of tools in the environment.  The aggregate baggage is larger than for 
  73. Ada or Ada 9X (given that the size of C++ alone is already as large as Ada 9X, 
  74. and at least as complex).
  75.  
  76. 2.  Second, even if implementations of the language are standardized (which is 
  77. far from true for C++) differences in the environment and its tools make 
  78. portability harder to achieve.  Programs can easily become contaminated with 
  79. environmental details.  To the C++ programmer who says: "this is no problem, 
  80. because if you just follow coding conventions the problems disappear", we can 
  81. only reply that these coding conventions are additional baggage that the 
  82. programmer must know, that they add to the cost of using the language, and 
  83. that they are inherently less safe than comparable features that are built 
  84. into the language.
  85.  
  86. 3.  Finally, the programmer's knowledge is less portable and thus devalued, 
  87. because a solution adopted in one shop will be foreign to another.
  88.  
  89. We conclude that the C++ culture requires a larger aggregate knowledge than 
  90. the Ada culture, that this knowledge is ill-defined at the interface between 
  91. language and environment, and that it results in lessened portability and thus 
  92. greater maintenance costs than comparable Ada software.
  93.  
  94.                  3.  The type model: what is an array?
  95.  
  96. In spite of the fact that arrays are one of the oldest composite types in 
  97. programming languages, there are sharp differences between their realization 
  98. in C++ and Ada.  C++ follows the C approach: arrays are closely related to 
  99. pointers, and the indexing operation is described directly in terms of pointer 
  100. arithmetic.  This has several consequences:
  101.  
  102. 1.  The indexing operation is not automatically checked.  The language 
  103. reference indicates that out-of-bounds indices are illegal, except that it is 
  104. allowed to point one element past the end of the array (for reasons having to 
  105. do with common programming idioms for iterating over an array); but there are 
  106. not automatic bound checks at run-time.  Given that indices out of bounds are 
  107. the most common type of run-time error, this makes the use of arrays in C++ 
  108. inherently less safe than in Ada.
  109.  
  110. 2.  There is no array assignment: if an array is a pointer, then an assignment 
  111. to the name of the array is a pointer assignment which aliases the array, not 
  112. a data transfer operation.
  113.  
  114. 3.  Multidimensional arrays are defined as arrays of arrays; multidimensional 
  115. arrays must be declared with constant bounds (after the first) and have no 
  116. built-in descriptors (such as Ada requires to support array attributes).  
  117. Linear algebra packages for example must carry explicit size parameters, or 
  118. else the user is forced to play aliasing tricks between one- and 
  119. multi-dimensional arrays, as is done in FORTRAN.  Thus the basic data type of 
  120. scientific programming is described in low-level storage terms.  In contrast, 
  121. multidimensional arrays in Ada are described in terms of formal operations of 
  122. an abstract type.  In this area, C++ is clearly a lower-level language.
  123.  
  124. 4.  All array types have the same index type; one cannot define an array over 
  125. an enumerated type, and there is never any type checking on indices.
  126.  
  127. Shortcoming 1) in particular is well-known and acknowledged by the C++ 
  128. community.  Stroustrup [S91] correctly describes arrays as low-level 
  129. structures and presents a user-defined vector class (on which indexing is 
  130. checked) as a better abstract type.  Unfortunately, the proper implementation 
  131. of the class requires exceptions, a feature which has only recently been 
  132. introduced into C++ and which is not widely (nor consistently) implemented 
  133. yet.  In the meantime, programming without index checking is akin to driving 
  134. without seat belts on the optimistic conviction that most drivers are sober.  
  135. This optimism pervades the C and C++ communities.  Ada programmers are more 
  136. wary of their surroundings.
  137.  
  138. We should also remark that compilers make a big effort to optimize the use of 
  139. built-in arrays, because they are the basic structure of many 
  140. compute-intensive programs.  Compilers are much less likely to treat 
  141. user-defined arrays with the same care (there are no anticipated versions of 
  142. LINPACK that use C++ vector classes).
  143.  
  144. We conclude that C++ software is less reliable than Ada and Ada 9X code, and 
  145. that for scientific programming C++ is a lower-level language than Ada.
  146.  
  147.                  4. Classes, Inheritance, and Objects
  148.  
  149. Object-oriented programming and design (OOP) has become the buzzword of the 
  150. decade.  Behind the obvious enthusiasm of the software community there lies 
  151. the correct perception that OOP simplifies the design and construction of 
  152. software systems.  The basic reason is ease of reuse.  The notion of object is 
  153. vague and has been used to mean variously abstract type active agent, message 
  154. receiver, etc.  (A good case can be made that Ada tasks are the perfect model 
  155. for objects and that Ada was one of the earliest object-oriented languages.)  
  156. But in fact the usefulness of OOP does not lie in this fuzzy notion of object.  
  157. Rather, it lies in the combination of inheritance, specialization by 
  158. extension, and dynamic dispatching.  The gain is in the amount of code that 
  159. one does not have to write, simply because one can obtain it by inheritance 
  160. from the previously defined software component.
  161.  
  162. Inheritance was already present, in a rigid form, in the type derivation 
  163. mechanism of Ada 83.
  164.  
  165. OOP brings the fundamental insight that types should be enriched by extending 
  166. what they inherit, rather than being mere copies of their ancestors.  Dynamic 
  167. dispatching, that is to say the type-safe run-time choice of the operation 
  168. that applies to a specific type extension, is real innovation in software 
  169. construction.
  170.  
  171. Ada 9X implements OOP by a straightforward extension of the notion of derived 
  172. type [AMSR].  Objects are no different from Ada83: they are entities that can 
  173. have values of a certain type.  The message-passing concept can still be 
  174. realized by means of tasks, but the more conventional concept of class is the 
  175. Ada 9X type extension:
  176.  
  177. type new_and_improved is new tried_and_true with record
  178.       this: bell;
  179.       that: whistle;
  180. end record;
  181.  
  182. procedure ring(thing: new_and_improved) is ...
  183.  
  184. The type new_and_improved inherits the primitive operations of its parent type 
  185. tried_and_true.  Those operations act on the components that are common to 
  186. both parent and child types.  In addition, the new type contains additional 
  187. components (bells and whistles) and one can define new operations (or override 
  188. inherited ones) which make use of the components in the extension.  There is 
  189. no special syntax to designate objects of such types, nor to invoke operations 
  190. that have formals of such types.  Furthermore, if the parent operation has 
  191. several parameters (or return value) of the parent type, then the signature of 
  192. the inherited operation is obtained by replacing every mention of the parent 
  193. type with the child type.  As in most other OOPLs, Ada 9X makes some basic 
  194. distinctions between types that can be extended in this fashion (tagged types) 
  195. and types that cannot (for example integers).
  196.  
  197. In contrast, the notion of class in C++ derives from that of structure, and 
  198. suggests that subprograms that apply to objects of a class are in some sense 
  199. part of those objects (class members).  This model, inherited from Smalltalk 
  200. and Simula, gives a privileged role to the first parameter of such a 
  201. subprogram, which is invoked with a special notation (as a qualified name).  
  202. In our experience, it is seldom useful to think of the operations as being 
  203. part of a value (unless they are entries in a task).  The Ada 9X model 
  204. provides the benefits of OOPS without this somewhat muddled notion of object.
  205.  
  206. Note also that C++ classes are the only encapsulation mechanism in the 
  207. language (if one excludes the use of files as modules), and thus they also 
  208. play the role that packages play in Ada.  This dual role is better served with 
  209. two separate notions.
  210.  
  211.                          4.1. Family interactions
  212.  
  213. The Ada 9X model also provides a more natural description of binary operations 
  214. (and in general operations that have several formals of the same tagged type).  
  215. Consider:
  216.  
  217. function merge(x, y: parent) return parent ;
  218. ...
  219. type child is new parent with record ...
  220. -- function merge(x, y: child) return child is inherited.
  221.  
  222. In the C++ model the member function has an implicit first parameter:
  223.  
  224. class parent {
  225. ...
  226. parent merge(parent)
  227. ...
  228. }
  229.  
  230. class child: public parent { ...
  231.  
  232. The class child inherits a function merge, whose second argument must be a 
  233. parent (not a child) and which returns a parent (not a child).  Thus the 
  234. inherited operation loses the homogeneity of the original.  Some complications 
  235. ensue.  (For example, the signature of a dispatching variant of merge must 
  236. mention the parent type, not the child, otherwise it is a different 
  237. operation.)  Because of this asymmetry, it is possible to subvert the 
  238. dispatching mechanism and to call a dispatching operation with invalid 
  239. arguments -- and unpredictable results.  In contrast, the Ada 9X dispatching 
  240. model specifies that all dispatching parameters must have the same type (more 
  241. precisely the same tag).  A predefined exception is raised if this condition 
  242. is violated.
  243.  
  244. We conclude that the Ada 9X model for type extension provides a cleaner 
  245. definition of binary operations.
  246.  
  247.                       4.2. The limits of friendship
  248.  
  249. The notion of friend functions and friend classes is one of the more 
  250. controversial aspects of C++.  Its defenders correctly point out that the 
  251. built-in privacy of class members that are not explicitly declared public 
  252. means that it is well-nigh impossible to write efficient code that makes use 
  253. of two distinct classes A and B: a member function of A will only have access 
  254. to the private representation of A, and will have to use a procedural 
  255. interface (with a potentially large execution penalty) to access the private 
  256. representation of B.  This is often unacceptable (the canonical example is 
  257. vector-matrix multiplication, when each is defined as a separate class, which 
  258. forces a large number of redundant index checks in the code).  By declaring 
  259. selectively certain functions as friends of a given class, the permission is 
  260. granted to write code using the private representation from outside of the 
  261. class.
  262.  
  263. Many consider this mechanism unsafe, and advise against its use.  In Ada, the 
  264. need for such a mechanism is lessened by the possibility of defining related 
  265. types in the same package.  Those types can be private, and yet functions 
  266. defined in (and exported by) the packaged can make use in their bodies of the 
  267. private representations of these types.  This style respects the interface 
  268. between interface and implementation, but requires more design discipline 
  269. (both types must be conceived simultaneously).
  270.  
  271. In Ada 9X, an additional mechanism exists to create related entities in 
  272. separate units: the hierarchical library model.  Child packages can 
  273. selectively request visibility of the private parts of the parent packages.  
  274. This mechanism is as expressive as the C++ friend declarations.  It is also 
  275. independent of inheritance.
  276.  
  277.                          5. Keeping track of time
  278.  
  279. Ada was the first mainstream language to incorporate constructs for 
  280. multitasking and for real-time programming.  It is still virtually the only 
  281. language to do so in a coherent fashion.  Ada 9X will have much more developed 
  282. real-time and synchronization facilities, in particular constructs for data 
  283. synchronization (protected records).  There are as yet no winning proposals 
  284. for tasking facilities in C++, and no hint of notions of real-time and 
  285. scheduling tools.  In this area C++ is a non-starter, even compared with 
  286. Ada83.
  287.  
  288. And yet C and C++ are used for programming real-time systems.  How is this 
  289. done?  By means of libraries in various stages of standardization, such as the 
  290. CIFO proposed standard.  Here again, "it can be done" in C++, if we regard 
  291. these large libraries as part of the greater C++ system.  Needless to say, as 
  292. long as these are not recognized standards, programs that use them will be 
  293. non-portable in subtle ways.  It may well be that a standard library of 
  294. real-time primitives will evolve and become part of C++, just as the stream 
  295. facility has evolved from an interesting user-defined class to a recognized 
  296. part of the language.  In the meantime, Ada 9X has the advantage of features 
  297. that are integrated from the beginning, with a well-understood interaction 
  298. between complex features (e.g., tasking and exception).  Ada 9X expands on the 
  299. tasking facilities of Ada with asynchronous transfer of control, protected 
  300. records, better user access to scheduling primitives, additional forms of 
  301. delay statements, and parametrized tasks.
  302.  
  303. We conclude that in the area of real-time programming Ada 9X is still without 
  304. any serious competition.
  305.  
  306.                    6. Generics are cheap and reliable
  307.  
  308. To maximize software reuse, it is important to be able to parametrize software 
  309. components, so that the same blueprint can be used in type-safe fashion for 
  310. different applications.  For example, a single sorting algorithm can be used 
  311. for arrays of different element types, as long as the element type is ordered 
  312. (i.e., has a comparison predicate).  The generic facility of Ada is an 
  313. excellent model of type parametrization.  In addition to type parameters with 
  314. specified operations (private and limited generic types) it is possible to 
  315. specify type parameters that belong to a given class of types (e.g., any 
  316. integer type), as well as value parameters and object parameters.
  317.  
  318. In contrast, C has no parametrization facilities.  The common practice is to 
  319. use the C preprocessor (a macro expander) to duplicate text with suitable 
  320. replacement, in order to simulate generic instantiation.  This mechanism is 
  321. purely lexical: there are no syntax or semantic checks attached to the macro 
  322. definition nor to each of its expansions.
  323.  
  324. The designer of C++ has recognized the need for a more disciplined 
  325. parametrization mechanism, and the latest version of the language describes 
  326. templates, a facility that is close in spirit to Ada generics.  A template 
  327. indicates that a unit has one or more class parameters.  In the simple case 
  328. there are no operations defined on a class parameter, so it is equivalent to 
  329. an Ada private generic type.  It is possible to include function parameters 
  330. that depend on a class parameter; this is equivalent to the use of generic 
  331. formal subprogram parameters in Ada.  There is an asymmetry between class 
  332. parameters and function parameters which is not present in Ada, and the syntax 
  333. forces repeated mentions of the template parameters (e.g., for each member 
  334. function body of a class template).
  335.  
  336. Ada 9X has an even richer set of parametrization mechanisms than Ada.  In Ada 
  337. 9X it is possible to specify generic derived types (where the actual is any 
  338. member of the class of the generic type) and generic formal packages (where 
  339. the actual is any instantiation of the generic formal package).  This later 
  340. form of parametrization is more powerful than what is available in C++, and is 
  341. akin to the use of functions and signatures in ML.  Both in terms of 
  342. expressiveness and clarity Ada 9X has a clear advantage over C++ here.
  343.  
  344.                          7. Multiple Inheritance
  345.  
  346. It might be argued that the multiple inheritance model of the current version 
  347. of C++ is definitely superior to what is proposed for Ada 9X.  This is a most 
  348. minor point: multiple inheritance (MI) is a programming style, not a universal 
  349. tool, and object-oriented practice of the last 10 years indicates that the 
  350. critical benefit of OOP, namely code reuse, is not substantially enhanced by 
  351. multiple inheritance.  Without denying that some programming situations 
  352. benefit from MI, we can state that its presence does not make or break an 
  353. object-oriented language.  Furthermore, the introduction of multiple 
  354. inheritance complicates the type model, complicates the implementation of 
  355. dynamic dispatching, and brings semantic difficulties that are solved by the 
  356. introduction of virtual base classes, a substantial complexity in its own 
  357. right.
  358.  
  359. A common use of multiple inheritance is to construct "mixins", but in most of 
  360. the examples we have seen, there is clearly a major and a minor parent; the 
  361. minor provides additional functionality to a type that is clearly an extension 
  362. of the major parent.  Programming techniques exist to obtain the effect of 
  363. mixins in Ada 9X, by combining type extensions with renaming:
  364.  
  365. type gizmo is ...
  366.       procedure fiddle(g: in out giizmo) ;
  367.       type enhanced is new old_and_reliable with record
  368. g: gizmo;
  369. end record;
  370. ...
  371. procedure fiddle(e: in out enhanced) is
  372. begin fiddle(e.g) ; end ;
  373.  
  374. This is equivalent to a C++ declaration where enhanced is defined as a class 
  375. that inherits both from old_and_reliable and from gizmo.  It does require a 
  376. few additional lines of Ada 9X code to obtain the same effect, but does not 
  377. require a complex additional feature.
  378.  
  379. Finally, a common use of multiple inheritance is to provide visibility.  What 
  380. would be done in Ada by the use of context clauses that name several packages, 
  381. can be achieved in C++ by inheriting from several classes.  Here again, 
  382. classes play the role of Ada packages rather than that of types.
  383.  
  384. We conclude that by rejecting multiple inheritance Ada 9X loses no significant 
  385. functionality, and gains in simplicity.
  386.  
  387.                            8. Appearance Counts
  388.  
  389. Ada programs read well.  This is acknowledged by all who have ever seen Ada 
  390. code, and it has a profound effect on program maintenance.  Readability was 
  391. one of the guiding criteria in the design of the syntax of Ada, and the design 
  392. is obviously successful.  One might say that Ada reads well because it sounds 
  393. right.  This not to say that Ada programmers move their lips when parsing Ada 
  394. code, but rather that reading carefully means hearing in one's mind, and it 
  395. helps if what one hears is pronounceable, in some very general sense.  Ada 
  396. text is dense in keywords, which some mistakenly consider noisy and redundant.  
  397. In fact, those keywords act as natural punctuation marks, and make program 
  398. reading more natural: a begin-end bracketing is more natural-sounding than 
  399. {..}.  The syntax of Ada 9X has the same qualities.  A few keywords have been 
  400. added, and others have been put to novel uses (e.g., with in type extensions), 
  401. but the sound of the language remains.
  402.  
  403. In contrast, C and C++ emphasize ease of writing rather than ease of reading.  
  404. Thus a greater use of operators, of terser notations (the conditional 
  405. expression, for example) and an absence of keywords (most noticeably in 
  406. declarations).  This makes C++ programs harder to transmit and to maintain.
  407.  
  408. Thus, seemingly minor considerations of surface syntax can have a profound 
  409. effect on the economics of using one language or another.  The readability of 
  410. Ada is a substantial money-saver.
  411.  
  412.                 8.1. The principle of minimal surprise
  413.  
  414. One of the most striking aspects of the C and C++ communities is the number of 
  415. language idioms that are part of the programming culture.  Idioms are 
  416. typically short, cryptic expressions with great power (this notion of idiom is 
  417. most intensely developed in the APL community).  The study of idioms has 
  418. produced such entertaining books as [F82], and it is clear that C and C++ 
  419. programmers enjoy enormously the game of "guess what this computes?".  The 
  420. question would not be fun if the answer were not in same way unexpected!  Thus 
  421. these languages systematically violate the informal rule of design known as 
  422. the principle of minimal surprise.
  423.  
  424. In contrast, this form of entertainment is completely missing from the Ada 
  425. culture.  Ada code does what it says, plainly.  It is interesting to compare 
  426. [MB92] with [f82].  A large number of the examples used Mendal and Bryan ask: 
  427. is the code legal?  The Ada programmer may be frustrated when his code is 
  428. rejected by the compiler, but he is much less likely to be surprised by the 
  429. behavior of code that compiles without error.
  430.  
  431.                                9. Conclusions
  432.  
  433. To compare Ada 9X and C++ is not easy, if for no other reason than C++ is a 
  434. language in flux for which no stable definition exists, no approved standard 
  435. reference, and no translator validation suite.  A glance at the list of 
  436. additions to the language since version 2.0 (see [S91]) is sufficient to 
  437. realize that active language design is still going on.  Of course, Ada 9X is 
  438. in even greater flux, but we know that the standardization mechanisms that 
  439. were successful from Ada83 will be in place here as well.  The ongoing ISO WG9 
  440. work (most recently at its meeting in Frankfurt, March 30 to April 3) ensures 
  441. that Ada 9X will be an international standard within a shorter time frame than 
  442. C++, and that the standard will have the active approval of all member 
  443. countries interested in programming languages for software systems.
  444.  
  445. C++ is for now the promise of a good language.  It is also a number of related 
  446. but not identical implementations, that are being used fairly widely in the 
  447. software industry.  If the DoD experience of the last quarter century can be 
  448. distilled to a single fact, it is that lack of portability and reusability are 
  449. the most direct causes of runaway software costs.  The strong standardization, 
  450. and the resulting portability of Ada code have proved their worth many times 
  451. over the past decade.  The use of a less well-defined tool would be a large 
  452. step backwards.
  453.  
  454. This being said, it would disingenuous to deny the current success of C++ in 
  455. the software community.  In our opinion, this success is mostly due to the 
  456. fact that C++ is much better than C, and for the legions of C programmers this 
  457. means a language that provides some measure of type checking, which is a large 
  458. improvement over their previous standards.  In addition, the classes of C++ 
  459. are a convenient tool for data abstraction and information hiding (very much 
  460. like Ada packages) and programmers are justifiably pleased to use them.  
  461. Finally, C and C++ benefit from an environment which is mostly written in the 
  462. same language, so that interface problems are fewer.
  463.  
  464. Although the C++ community would never state it so boldly, it appears clear to 
  465. us that C++ is to some extent a reaction to Ada.  By extending C with some of 
  466. the best ideas of Ada (strong typing, exceptions, generics) C++ did in some 
  467. measure catch up to Ada.  Ada 9X offers the chance to leapfrog C++, by 
  468. extending the language in two critical areas: object-oriented programming 
  469. (with type extensions) and real-time programming (with protected records and 
  470. flexible scheduling).  This comes on top of a language with incomparable type 
  471. safety, (which should be contrasted with the "user beware" philosophy of C and 
  472. C++) and a culture that is now 10 years mature and that yields cleaner and 
  473. safer software than that produced with any other systems programming language.  
  474. Ada 9X seems well worth the wait.
  475.  
  476.                                  References
  477.  
  478. [AMSR] Intermetrics, Ada 9X Mapping Specification and Rationale, version 4.1 
  479. Boston, MA, Intermetrics, March 1992.
  480.  
  481. [F82] Allan R. Feuer, The C Puzzle Book, Englewood Cliffs, NJ, Prentice-Hall, 
  482. 1982.
  483.  
  484. [H91] Cay S. Horstmann, Mastering C++, New York, Wiley and Sons, 1991.
  485.  
  486. [MB92] Geoffrey O. Mendal and Douglas L. Bryan, Exploring Ada, volumes 1 and 
  487. 2, Englewood Cliffs, NJ, Prentice-Hall, 1992.
  488.  
  489. [S91] Bjarne Stroustrup, The C++ Programming Language, 2d edition.  Reading 
  490. MA, Addison-Wesley, 1991.
  491.  
  492.                             **********************
  493.  
  494.                        Reprinted with permission.
  495.  
  496.                  Ada Information Clearinghouse (AdaIC)
  497.                                P.O. Box 46593
  498.                        Washington, DC  20050-6593
  499.              703/685-1477, 800/AdaIC-11, FAX 703/685-7019
  500.            adainfo@ajpo.sei.cmu.edu; CompuServe 70312,3303
  501.  
  502. The AdaIC is sponsored by the Ada Joint Program Office and operated by IIT 
  503. Research Institute.
  504.  
  505.  
  506.  
  507.