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.
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
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
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
[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
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
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
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.
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
[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 Maserati. An ATV (all terrain vehicle) is more fun, since you can "play around" by driving through fields, streams, sidewalks, and the like. A Maserati, 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.
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
E-mail the author
[ C++ FAQ Lite
| Table of contents
| Subject index
| About the author
| ©
| Download your own copy ]
Revised Mar 1, 2006