[27] Learning C++ if you already know Smalltalk
(Part of C++ FAQ Lite, Copyright © 1991-2000, Marshall Cline, cline@parashift.com)


FAQs in section [27]:


[27.1] What's the difference between C++ and Smalltalk?

Both fully support the OO paradigm. Neither is categorically and universally "better" than the other. But there are differences. The most important differences are:

Note: Many new C++ programmers come from a Smalltalk background. If that's you, this section will tell you the most important things you need know to make your transition. Please don't get the notion that either language is somehow "inferior" or "bad", or that this section is promoting one language over the other (I am not a language bigot; I serve on both the ANSI C++ and ANSI Smalltalk standardization committees). Instead, this section is designed to help you understand (and embrace!) the differences.

TopBottomPrevious sectionNext section ]


[27.2] What is "static typing," and how is it similar/dissimilar to Smalltalk?

Static typing says the compiler checks the type safety of every operation statically (at compile-time), rather than to generate code which will check things at run-time. For example, with static typing, the signature matching for function arguments is checked at compile time, not at run-time. An improper match is flagged as an error by the compiler, not by the run-time system.

In OO code, the most common "typing mismatch" is invoking a member function against an object which isn't prepared to handle the operation. E.g., if class Fred has member function f() but not g(), and fred is an instance of class Fred, then fred.f() is legal and fred.g() is illegal. C++ (statically typed) catches the error at compile time, and Smalltalk (dynamically typed) catches the error at run-time. (Technically speaking, C++ is like Pascal —pseudo statically typed— since pointer casts and unions can be used to violate the typing system; which reminds me: only use pointer casts and unions as often as you use gotos).

TopBottomPrevious sectionNext section ]


[27.3] Which is a better fit for C++: "static typing" or "dynamic typing"? UPDATED!

[Recently added cross references to evilness of macros (on 3/00). Click here to go to the next FAQ in the "chain" of recent changes.]

[For context, please read the previous FAQ].

If you want to use C++ most effectively, use it as a statically typed language.

C++ is flexible enough that you can (via pointer casts, unions, and #define macros) make it "look" like Smalltalk. But don't. Which reminds me: try to avoid #define: it is evil in 4 different ways: evil#1, evil#2, evil#3, and evil#4.

There are places where pointer casts and unions are necessary and even wholesome, but they should be used carefully and sparingly. A pointer cast tells the compiler to believe you. An incorrect pointer cast might corrupt your heap, scribble into memory owned by other objects, call nonexistent member functions, and cause general failures. It's not a pretty sight. If you avoid these and related constructs, you can make your C++ code both safer and faster, since anything that can be checked at compile time is something that doesn't have to be done at run-time.

If you're interested in using a pointer cast, use the new style pointer casts. The most common example of these is to change old-style pointer casts such as (X*)p into new-style dynamic casts such as dynamic_cast<X*>(p), where p is a pointer and X is a type. In addition to dynamic_cast, there is static_cast and const_cast, but dynamic_cast is the one that simulates most of the advantages of dynamic typing (the other is the typeid() construct; for example, typeid(*p).name() will return the name of the type of *p).

TopBottomPrevious sectionNext section ]


[27.4] How do you use inheritance in C++, and is that different from Smalltalk? UPDATED!

[Recently renamed "subclass" to "derived class" (on 7/00). Click here to go to the next FAQ in the "chain" of recent changes.]

Some people believe that the purpose of inheritance is code reuse. In C++, this is wrong. Stated plainly, "inheritance is not for code reuse."

The purpose of inheritance in C++ is to express interface compliance (subtyping), not to get code reuse. In C++, code reuse usually comes via composition rather than via inheritance. In other words, inheritance is mainly a specification technique rather than an implementation technique.

This is a major difference with Smalltalk, where there is only one form of inheritance (C++ provides private inheritance to mean "share the code but don't conform to the interface", and public inheritance to mean "kind-of"). The Smalltalk language proper (as opposed to coding practice) allows you to have the effect of "hiding" an inherited method by providing an override that calls the "does not understand" method. Furthermore Smalltalk allows a conceptual "is-a" relationship to exist apart from the inheritance hierarchy (subtypes don't have to be derived classes; e.g., you can make something that is-a Stack yet doesn't inherit from class Stack).

In contrast, C++ is more restrictive about inheritance: there's no way to make a "conceptual is-a" relationship without using inheritance (the C++ work-around is to separate interface from implementation via ABCs). The C++ compiler exploits the added semantic information associated with public inheritance to provide static typing.

TopBottomPrevious sectionNext section ]


[27.5] What are the practical consequences of differences in Smalltalk/C++ inheritance? UPDATED!

[Recently renamed "subclass" to "derived class" (on 7/00). Click here to go to the next FAQ in the "chain" of recent changes.]

[For context, please read the previous FAQ].

Smalltalk lets you make a subtype that isn't a derived class, and allows you to make a derived class that isn't a subtype. This allows Smalltalk programmers to be very carefree in putting data (bits, representation, data structure) into a class (e.g., you might put a linked list into class Stack). After all, if someone wants an array-based-Stack, they don't have to inherit from Stack; they could inherit such a class from Array if desired, even though an ArrayBasedStack is not a kind-of Array!

In C++, you can't be nearly as carefree. Only mechanism (member function code), but not representation (data bits) can be overridden in derived classes. Therefore you're usually better off not putting the data structure in a class. This leads to a stronger reliance on abstract base classes.

I like to think of the difference between an ATV and a Maseratti. An ATV (all terrain vehicle) is more fun, since you can "play around" by driving through fields, streams, sidewalks, and the like. A Maseratti, on the other hand, gets you there faster, but it forces you to stay on the road. My advice to C++ programmers is simple: stay on the road. Even if you're one of those people who like the "expressive freedom" to drive through the bushes, don't do it in C++; it's not a good fit.

TopBottomPrevious sectionNext section ]


E-Mail E-mail the author
C++ FAQ LiteTable of contentsSubject indexAbout the author©Download your own copy ]
Revised Jul 10, 2000