dcw@doc.ic.ac.uk (Duncan C White) (06/05/87)
A friend and I are trying to assess the suitability of C++ as a replacement for SIMULA, in the context of teaching a 2nd year UG Computer Science course about Simulation. We have found one basic difference between the two, and various sub-problems, which we would like to ask more experienced C++ programmers about. If any of the questions are stupid, or ignorant, please be kind and gently correct us... *** WARNING: THIS ARTICLE IS APPROX 300 LINES LONG... HIT 'j' NOW IF YOU'RE *** NOT INTERESTED.. Terminology/Abbreviations: ------------------------- We are using more general object-orientated terms in place of C++'s ones. Specifically: o a method a procedure in a class o a subclass a descendant class o a superclass an ancestor class "The Book" is the 'C++ Programming Language' [ Bjarne Stroustrup, AT&T ] A reference such as "S:7.5.2" means "Section 7.5.2 of the Book" Also, we will use a sort of "pseudo-C++/SIMULA" for all the examples, irrespective of minor details like syntax... :-) Question 1: There seems to be an ambiguity in the Book which could cause ---------- a lot of confusion if not cleared up: For example, given the following [an extract from 'class hierarchies' S:7.5.2] class employee class manager : employee class director : manager class vice_president : manager class president : vice_president there are several SUBCLASSES of employee: manager, director, vice_president and president whereas manager is the ONLY IMMEDIATE SUBCLASS of employee. [In general, however, there may be several IMMEDIATE SUBCLASSES: director AND vice_president are BOTH immediate subclasses of manager] Which of these terms corresponds to 'derived class' ? Similarly, there is ONLY one IMMEDIATE SUPERCLASS of director [manager] : does this correspond to the base class definition ? Or is employee a base class of director, as well ? A Basic Difference : After some initial experimenting [ which took us 3 ------------------ days, and involved fairly heavy rewriting of this article !! ], we became aware of a very basic difference between SIMULA and C++ : We had assumed that the basic facilities SIMULA and C++ provide would be the same : after all, the Introduction says that C++ was designed [ via C with classes ] as an alternative to SIMULA, but less expensive at run-time. However, SIMULA allows the following: > class vehicle ... // class defns > class car : vehicle ... > class fourwheeler : car ... > > ref( vehicle ) v; NOTE : in SIMULA, all class variables are declared and initialised separately so in this example, 'v' is declared as a reference to a vehicle, [reference appears to be the same term as in C++]. v has not been initialised yet. The C++ style declaration 'vehicle v' is meaningless in SIMULA. Clearly, then, v could be initialised [ SIMULA actually uses ':-' as a special assignment operator for refs ] by the following: > v = new vehicle; However, SIMULA allows an important 'other' style of initialization : > v = new car; which initialises v, but not to a vehicle-instance: to a car-instance [ car must be a subclass of vehicle ] C++ objects [vehemently] to this kind of use : probably because it has many implications for run-time behaviour. This basic problem comes to light again and again : o You can't declare a function which takes a parameter of type vehicle, and then call it with an expression which is a car-instance. o You can't define a 'list of vehicles' into which you can put any subclass-instances [ cars, planes, boats, pogo-sticks, minis, fords, aston martins etc.. ] o Associated operators like 'in' and 'qua' [ see below ] aren't available It seems to us, that the omission of such facilities in C++ is a major obstacle to 'object-orientated' programming : the usual SIMULA approach no longer works. Why the hell can't a list of vehicles contain some cars, some planes, some horse-drawn carriages, and some pogo-sticks ?? Question 2: Is this omission as serious as it appears ? Can the same ---------- facilities be provided another way, or is there a separate "C++ programming metaphor" which entails a different way of analysing problems so that the missing features are never needed ?? NOTE: The Book seems to suggest two related techniques : generic vectors [ S:1.16 ] which suggests writing macros to 'build' class definitions for specific subclass lists [ eg, declare( vector, int ) ] However, this builds an 'integer-vector' class definition, rather than a 'vector of things which are any subclasses of integer' AND: polymorphic vectors [ S:17 ] However, this technique seems to rely on 'void *' to contain a pointer to the elements: surely this completely defeats the type-checking scheme ? Explanation of 'in' and 'qua' : ----------------------------- 1). The boolean SIMULA function : i in c returns true if the instance, i, is an instance of the given class, c, or if i is an instance of any subclass of c [ false otherwise ] For example: a 'car' instance is in 'car' a 'car' instance is ALSO in 'vehicle' a 'fourwheeler' instance is in 'fourwheeler', 'car' and 'vehicle' 2). The polymorphic SIMULA function : i qua c "qualifies" the instance, i, as a class, c. [ more explanation below example ] For example: given the following: > ref( vehicle ) v; > v = new car; // vehicle v is a car: C++ would already object The following use, despite actually being logically correct, fails to compile : > print v.wheels; // attempt to print the number of wheels > // that the car-instance v has. whereas this is ok: > print (v qua car).wheels; Note: the semantics of qua are a strange mixture of compile-time and run-time events. At compile-time, v must be an instance of a car, or an instance of a superclass of car, otherwise a compile time error is generated. However, at run-time, v is checked to see that it actually is 'in' car, and a fatal run-time error is generated if not. Finding the Immediate Superclass: We realized that 'in' was not defined -------------------------------- some time before we understood the Basic Problem, and we tried to define 'in' ourselves : It seemed quite simple, we thought, just have a static name for each class and then search upwards through the class hierarchy. This would mean declaring one universal superclass, which would contain the function 'in'. All other classes would be subclasses of this, inheriting 'in' from the universal class [ therefore, the code would only need to be defined once ! ] Question 3 : Can anyone think of a nicer way to implement in ? ---------- We tried : >typedef int boolean ; > >class universal_class { > static char *name = "universal_class"; This, of course, caused us to run straight into the 'initialization of static class members' problem discussed a few articles ago.. ( of course, we didn't read that article until we had wasted several hours trying various increasingly desperate and mucky methods ... :-) Anyway, after we had seen the solution to this problem, we continued: > boolean in( char *str ) > { > return strcmp( this.name, str ) == 0 > || ( > strcmp( this.name, "universal_class" ) > && super::in( str ) > ); > } >}; // end class universal_class We had naively assumed that super, or something very like it, would exist, and would allow you to use a method of the GENERAL immediate superclass of an instance, rather than the method of the instance itself. We knew that, if you know the name of the immediate superclass, you can use: superclass_name::method but this would require a version of 'in' for every subclass. Question 4 : Does C++ have an equivalent of super ? Can it be defined ? ---------- As soon as we started thinking about it, we realised that SIMULA does not have 'super' either. We couldn't understand why this function was not available in SIMULA, since SIMULA undoubtedly maintains enough run-time information to implement it. However, the only concrete use we have thought of [so far] for 'super' is when defining 'in'.... So, we supppose, because SIMULA has 'in' already defined, it doesn't need to have 'super', whereas C++ has neither 'in' nor 'super'.. Conclusion: ---------- There are many aspects in C++ which we like [ operator overloading and true reference variables especially ] but it does seem to be, in some sense, a "weaker kind" of class-based language than SIMULA. Please respond to this message by e-mail, and I will summarise to the net if there is much interest.. Apologies for the length of this article... Finally, nacnuD, emit ruoy rof sknahT (well, everyone says I'm backward :-) ----------------------------------------------------------------------------- JANET address : dcw@uk.ac.ic.doc| Snail Mail : Duncan White, --------------------------------| Dept of Computing, This space intentionally | Imperial College, left blank...... | 180 Queen's Gate, (paradoxical excerpt from | South Kensington, IBM manuals) | London SW7 ---------------------------------------------------------------------------- Tel: UK 01-589-5111 x 4982/4991 ----------------------------------------------------------------------------