0% found this document useful (0 votes)
12 views11 pages

C++: Beyond Object-Oriented Programming

This paper by Bjarne Stroustrup discusses the versatility of C++ as a programming language that supports multiple programming styles beyond just object-oriented programming. It emphasizes the importance of defining 'object-oriented' in a practical sense, highlighting key features such as abstraction, inheritance, and polymorphism, while also acknowledging the value of other programming paradigms. Stroustrup argues that C++ is a multi-paradigm language designed to facilitate a range of programming techniques, making it suitable for various application needs.

Uploaded by

hoboman
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
12 views11 pages

C++: Beyond Object-Oriented Programming

This paper by Bjarne Stroustrup discusses the versatility of C++ as a programming language that supports multiple programming styles beyond just object-oriented programming. It emphasizes the importance of defining 'object-oriented' in a practical sense, highlighting key features such as abstraction, inheritance, and polymorphism, while also acknowledging the value of other programming paradigms. Stroustrup argues that C++ is a multi-paradigm language designed to facilitate a range of programming techniques, making it suitable for various application needs.

Uploaded by

hoboman
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Addendum to OOPSLA95 Proceedings, ACM OOPS Messenger, October 1995

Why C++ is not just an Object-Oriented Programming Language

Bjarne Stroustrup
AT&T Bell Laboratories
Murray Hill, New Jersey 07974

ABSTRACT

C++ directly supports a variety of programming styles. In this, C++ deliberately differs
from languages designed to support a single way of writing programs. This paper briefly
presents key programming styles directly supported by C++ and argues that the support
for multiple styles is one of its major strengths. The styles presented include: traditional
C-style, concrete classes, abstract classes, traditional class hierarchies, abstract classes
and class hierarchies, and generic programming. To provide a context for this overview, I
discuss criteria for a reasonable and useful definition of ‘‘object-oriented programming.’’
1 Introduction oriented is great’’ or that ‘‘really great techniques
are really object-oriented.’’ You simply cannot
There are many tools and techniques that can help
ask someone to bet their company’s future on
in our effort to build useful, economical, and
vague promises phased in ill-defined terms. Nor
maintainable systems. To complete ambitious
is a well-polished and logically coherent semi-
and complex projects, we rely on a wide variety
mathematical treatment of the subject of direct
of techniques and tools that must work together.
practical use.
The title of this paper singles out a program-
We need to define ‘‘object-oriented’’ to be
ming language†. However, the real topic is pro-
something specific so that we can point out spe-
gramming, or if you prefer a longer formulation,
cific benefits and risks associated with its use.
the design and implementation of systems. A
We must also be specific about what is not
programming language is just one of the means
object-oriented, and what benefits and lack of
by which we try to achieve our goals.
benefits we can expect from various non-object-
The definition of ‘‘object-oriented program-
oriented techniques.
ming’’ is no longer a popular topic of discussion
Consequently, this paper starts out discussing
at major conferences. A practical definition of
what makes a good definition of ‘‘object-
‘‘object-oriented programming,’’ ‘‘object-
oriented.’’ Next, I present a range of useful tech-
oriented analysis,’’ ‘‘object-oriented design,’’
niques which may or may not be object oriented
‘‘object-oriented technology,’’ etc., is, however, a
and discuss their advantages and disadvantages.
burning issue for people who want to turn the
oft-repeated promises made for techniques and
2 Defining ‘‘Object-oriented’’
languages called ‘‘object-oriented’’ into reality in
everyday projects. It has become a practical To be useful and intellectually honest, a definition
rather than academic topic of discussion. What is of ‘‘object-oriented’’ must
‘‘object-oriented technology?,’’ what benefits can [1] not be a mere synonym for ‘‘good,’’
be expected from it? at what risks?, how do those [2] not exclude most accepted meanings,
techniques, benefits, and risks compare with those [3] have a firm historical basis,
associated with alternatives? [4] exclude something.
A systems builder trying to explain to an Not everything good is object- oriented, and not
accountant why money should be spent for tools everything object-oriented is good. I think I can
supporting object-oriented techniques needs more support both claims from experience. I have seen
than a statement to the effect that ‘‘object- examples of the latter often enough: it is not
__________________
† This paper is primarily based on an invited talk with the same title given at OOPSLA’95 in Austin Texas. The style of this paper is
clearly affected by its origins as a relatively short talk. I would have preferred this paper to be either much longer or much shorter, but
I did not have the time to do either.
-2-

uncommon to find programs that apply techniques programming languages without classes, such as
usually deemed object-oriented extensively or C, Fortran4, and Pascal, are excluded. Languages
even exclusively, yet are hard to comprehend, that lack direct support for inheritance or run-time
hard to maintain, and perform abysmally. Such binding, such as Ada88 and ML are also
examples occur in every programming language. excluded.
But then, of course, some people respond ‘‘that ML is a good example of something that is
just proves that the program wasn’t truly object- good but not object-oriented. I like ML; it is an
oriented.’’ To which the answer must be that interesting, innovative, and powerful language,
either the term has become meaningless or there but it is functional rather than object-oriented and
must be something good beyond what is called its polymorphism is resolved at compile time
‘‘object-oriented.’’ rather than at run-time. Thus, saying that ML isn’t
On the other hand, when we define ‘‘object- object-oriented is not a criticism, it’s an observa-
oriented,’’ we must not be too exclusive. Object- tion about definitions and the nature of ML.
oriented programming is a broad intellectual dis- Techniques and tools are object-oriented if
cipline, not the mere use of specific language fea- and only if they support the use of object-oriented
tures. Attempts to define ‘‘object-oriented’’ to programming. For example, a design method is
mean ‘‘what I’m selling’’ are not uncommon, but object-oriented if its regular and proper use leads
are fundamentally sleazy. to programs that exploit abstraction, inheritance,
Any definition of ‘‘object-oriented’’ should be and polymorphism where appropriate. I strongly
historically reasonable. Words are only useful for prefer design methods that directly and naturally
communication, really only mean something, if support the use of at least one of the major
we agree on a meaning for them. There are sev- object-oriented languages supporting in ways that
eral plausible, logically coherent, and mutually exploit its features in an idiomatic way.
contradictory definitions of ‘‘object oriented’’ in For example, it is often possible to simplify
use. However, the mainstream usage stems application code by hiding objects with different
directly from the ideas pioneered by programming representations and different implementation
language Simula and the design techniques it was details behind a common ‘‘abstract’’ interface
developed to support. The communities of pro- (see §6.4 and §6.6). Conversely, the implementa-
grammers and designers centered around lan- tion of related concepts can often be greatly sim-
guages such as C++, CLOS, Eiffel, Object Pascal, plified by exploiting commonality through inheri-
and Smalltalk have contributed much to this tradi- tance (see §6.5 and §6.6). A major purpose of
tion. design methods and the CASE tools that com-
A meaningful definition of any concept must monly support them is to make design simpler,
exclude something. more regular, and more predictable. Thus, to earn
the label ‘‘object-oriented,’’ a design method
3 A Broad Definition of ‘‘Object-oriented’’ must regularly and predictably help the discovery
of commonality that can be exploited in these
Given these general criteria for a definition of
ways. Ideally, an object-oriented design method
’’object-oriented’’ you can find several plausible
must strongly encourage the expression of this
candidates, and several communities have their
commonality using the most appropriate facilities
own definitions. However, I suggest we stick to
in one or more of the languages supporting
the traditional definition of object-oriented used
object-oriented programming. Minimally, the
within broad communities of programmers. A
method and its supporting tools must not be a hin-
language or technique is object-oriented if and
drance to the use of object-oriented facilities in
only if it directly supports:
the programming language used to implement the
[1] Abstraction – providing some form of
design. Much confusion arise because not every
classes and objects.
design method that claims to be object-oriented
[2] Inheritance – providing the ability to build
does that.
new abstractions out of existing ones.
Please remember that I’m looking for a practi-
[3] Run-time polymorphism – providing some
cal understanding of the notion of ‘‘object-
form of run-time binding.
oriented’’ rather than a formal definition. A for-
This definition includes all major languages com-
mal definition is useful, indeed it may be essen-
monly referred to as object-oriented: Ada95, Beta,
tial. However, to be relevant, a formal definition
C++, CLOS, Eiffel, Simula, Smalltalk, and many
must match a coherent view of what the formal
other languages fit this definition. Classical
-3-

definition is meant to specify precisely. relationships are not hierarchal. Some entities
simply do not obey the rules of a particular
4 Purity object-oriented language. Some things that you
build in an object-oriented world are manipulated
There has been much debate about ‘‘purity,’’ in
from the outside so that it is difficult to make
the context of languages supporting object-
guarantees about the way they are used.
oriented programming. In my opinion, much of
that discussion is confused by the – often
5 C++ Design Ideals
unstated – assumption that not only does
‘‘object-oriented’’ imply ’’good,’’ but also by the I felt the need for facilities outside what is con-
further assumption that only ‘‘object-oriented’’ ventionally called ‘‘object-oriented,’’ so I sup-
features are good. Consequently, it is – wrongly plied some in C++. However, C++ isn’t meant to
– assumed that a language that provides features be everything to everybody. No one program-
deemed non-object-oriented must be worse than a ming language and no one view of how to write
language that does not. People who like a lan- programs is sufficient for everything.
guage to support classes as part of a hierarchy Constraints-based programming, logic program-
only and functions/methods attached to one spe- ming, functional programming, and various forms
cific class only often call such a language ‘‘a of concurrent programming are examples of good
pure object-oriented language.’’ If we don’t like and useful styles of programming not supported
the idea of restricting the definition of classes and by C++.
functions that way we can call such a language No single language can support every style.
‘‘just an object-oriented programming language.’’ However, a variety of styles can be supported
I prefer to have more facilities available than within the framework of a single language.
can be provided by methods defined on classes Where this can be done, signifcant benefits arise
within a single hierarchy. A lot of good design from sharing a common type system, a common
goes beyond that relatively narrow domain. Inci- toolset, etc. These technical advantages translate
dentally, I have come to dislike the adjective into important practical benefits such as enabling
‘‘hybrid’’ as used to distinguish ‘‘pure’’ object- groups with moderately differing needs to share a
oriented systems from others. Too often, language rather than having to apply a number of
‘‘hybrid’’ is used in a prejudicial manner. If I specialized languages.
must apply a descriptive label, I use the phrase C++ was designed to support a range of styles
‘‘multi-paradigm language’’ to describe C++. that I considered fundamentally good and useful.
Whether they were object-oriented, and in which
4.1 Use of Language Features sense of the word, was either irrelevant or a minor
Even when all the features required to support concern:
object-oriented programming are available, you [1] Abstraction – the ability to represent con-
don’t need to use them all the time. Some classes cepts directly in a program and hide inci-
just don’t belong in a hierarchy and some func- dental details behind well-defined inter-
tions don’t belong to any particular object. faces – is the key to every flexible and
The key to maintainable, efficient, and evolv- comprehensible system of any significant
able programs isn’t particular language features. size.
It is the ability to develop concepts needed for a [2] Encapsulation – the ability to provide
solution and to express them clearly in a program. guarantees that an abstraction is used only
Language features exist to make such expression according to its specification – is crucial
simple and direct. to defend abstractions against corruption.
Object-oriented programming can be done in a [3] Polymorphism – the ability to provide the
language lacking one or more of the features same interface to objects with differing
required to directly support object-oriented pro- implementations – is crucial to simplify
gramming. However, doing so is unnecessarily code using abstractions.
difficult, very difficult to support with tools, and [4] Inheritance – the ability to compose new
often prohibitively expensive. abstractions from existing one – is one of
Furthermore, there are things that can’t be the most powerful ways of constructing
expressed directly using only the ‘‘pure’’ object- useful abstractions.
oriented constructs mentioned above. For exam- [5] Genericity – the ability to parameterize
ple, some entities belong together, but their types and functions by types and values –
-4-

is essential for expressing type-safe con- leads to more extensible systems than a require-
tainers and a powerful tool for expressing ment to fit each individual ‘‘foreign’’ facility into
general algorithms. the language framework.
[6] Coexistence with other languages and sys- Over the years, we have seen spectacular
tems – essential for functioning in real- improvements both in hardware performance and
world execution environments. in compilation techniques. However, run-time
[7] Run-time compactness and speed – essen- efficiency and compact representation is still
tial for classical systems programming. absolutely essential to many people.
[8] Static type safety – an integral property of Static type safety is an essential part in my
languages of the family to which C++ view of both design and implementation (see, for
belongs and valuable both for guaranteeing example [Stroustrup,1991]). The guarantees pro-
properties of a design and for providing vided and the discipline of design imposed have
run-time and space efficiency. been found extremely valuable by many people
These facilities and general properties can be sup- working in a wide range of application areas.
ported in several alternative ways. For example, Static type checking is of course not a panacea,
one programming language may support a facility but it is something I would not attempt major pro-
in its core language where another supports it in a jects without.
library. Similarly, a facility provided by a run- The fundamental ideal of C++ is actually the
time mechanism in one language may be provided fundamental ideal for a lot of languages:
by a compile-time mechanism in another.
center box; c. Represent concepts and relation-
The requirement for coexistence is essential
ships between concepts directly and affordably.
for any language claiming to be general-purpose.
Looking at the world from the perspective of a Naturally, there are many ways of approaching
given programming language, we find that almost this ideal. It is worth remembering that all of the
every real-life system contain parts that are writ- languages usually mentioned in a discussion of
ten in others languages and designed according to practical use of object-oriented techniques are
principles foreign to that language. To be suitable vehicles for good design. A rational dis-
general-purpose, a language must somehow take cussion of languages is one of relative merits,
the unpredictable, ugly, and constantly changing applicability to specific problem areas, and per-
demands of program fragments written in ‘‘other sonal preferences, rather than one of absolutes.
languages’’ into account. Representing concepts directly is a restate-
To be genuinely general purpose, a language ment and possibly a generalization of ideas relat-
must possess facilities that allow it to share data ing to data abstraction and information hiding.
with program fragments written in other lan- Representing hierachical relationships is the tradi-
guages, to invoke code fragments written in other tional key to object-oriented programming. There
languages, and have code invoked by code written are, however, clean and useful relationships that
in other languages. For example, systems relying are not hierarchical yet can still be represented
on callbacks can be rather ugly to program, but directly in a program (for example, see §6.3 and
not being able to use such systems in a direct and §6.7).
idiomatic way would be crippling for a language Being more concerned with producing good
as a tool for real-world programming. In many software than with finding the most elegant
languages, a common use of ‘‘foreign’’ code is expression of ideas in the abstract, I insist on
exactly to violate the languages rules: to do things affordability. Affordability is a multi-facetted
that can’t be done – or can’t be done efficiently – issue that involves not only run-time efficiency,
in the language itself. but also availability of suitable hardware, avail-
Alternatively, access to facilities in ’’the out- ability of designers and programmers comfortable
side world’’ could be carefully fitted into the with new techniques, etc.
framework of the object-oriented programming
language through special facilities in the run-time 6 Programming Style and Language Features
environment or in libraries. However, accessing
I will now give examples of programming styles
facilities in the manner they were meant to be
and language features supporting them. Some are
used is often easier and less awkward than to fit
commonly referred to as ‘‘object-oriented,’’ some
them into our language framework. A general
are not, but that doesn’t prevent me from recom-
mechanism for accessing ‘‘foreign’’ code also
mending them in some contexts.
-5-

6.1 Conventional Notation date and modify it use to the new definition.
There are aspects of conventional code and con- The reason that the set of functions is rarely
ventional notation that I would like to see main- complete is that there is no incentive to make it
tained even in a strictly object-oriented overall so. A programmer can always write new func-
design. Being able to say plain square root of tions accessing the date structure, and the domi-
two, sqrt(2) is nice, and so is the ability to nant culture encourages the programmer to do so.
write x+y*z and know that it means add x to the Writing a new function that is ‘‘just right’’ for the
product of y and z. We have about 400 years of job, carries no overhead, and relies on no poten-
experience with such notation and it is deeply tially untrustworthy code is often considered bet-
ingrained in our technical culture. ter than improving a standard and general-purpose
set of access functions and using it. Often, it is
6.2 Concrete Types also far easier. This trend is typically reinforced
Very simple concepts, such as integers, float- by poor documentation.
ing point numbers, complex numbers, points,
lines, pairs, dates, disk locations, bcd characters, 6.2.2 A Concrete Class
error messages, currency, are usually not consid- A simple Date type can remedy most of the
ered suitable topics for discussion in academic problems related to using a data structure directly.
articles or at conferences. These are usually con- Consider:
sidered too simple to merit discussion. However, class Date {
the mundane is often statistically more significant public:
than the sophisticated. // public interface, consisting
Provided they can be implemented in a way // of non-virtual functions
that is simple, elegant, efficient and flexible private:
enough, I consider such simple concepts excellent // representation and other
candidates for independent proper types – as // implementation details
};
opposed to presenting them to users as plain data
structures or as parts of a larger class hierarchy. Such a Date type will provide
Consequently, part of a design effort should focus [1] constructors specifying how objects of the
on these little abstractions. These very concrete type are to be initialized;
types should be designed carefully and supported [2] functions for examining a Date; these
well. functions will be explicitly declared not to
To illustrate why, I’ll contrast this approach to modify the value of the object;
the use of a plain data structure and to the use of [3] functions for manipulating Dates without
class hierarchies. To make this discussion con- actually having to know the details of the
crete, I’ll use the example of a date. representation or fiddle with the intricacies
of the implementation.
6.2.1 Structures and Functions In addition, Dates can be freely copied.
The simplest way of presenting a date in a pro- This set of member functions supplied as
gram is simply to specify its data layout. For members of Date should be those that provide a
example: basic semantics for a Date and also requires
struct date { direct access to the representation of Date to be
// representation implemented.
}; The set of member functions should be almost
minimal; many operations that users would find
Given that, programmers can do anything at all convenient can be supplied separately (see §6.3).
with dates. That ‘‘anything at all’’ is the I dislike classes with dozens or even hundreds of
strength and weakness of this idea. Naturally, a member functions. Such a class does not repre-
‘‘standard’’ set of functions is usually provided to sent a well-thought-out concept; it’s a glorified
manipulate a structure such as date. However, data structure produced by somebody who
such a set of functions is rarely complete, and couldn’t decide on what was really wanted.
even when it is, programmers find reasons to The member functions are declared non-
manipulate dates directly. Consequently, it is virtual to ensure that there is no time or space
usually not possible to change the definition of overheads involved in using this Date, and to
date after the initial release of the software; it is ensure that the semantics of Date cannot be
simply too difficult to track down every use of a
-6-

modified later. Similarly, the representation of conscious design effort typically results in
Date is declared private to prevent access by a better thought out, more comprehensive,
any function not explicitly mentioned in the class and better documented concept. In princi-
itself. ple, this could equally well be done for the
The representation of a concrete type should plain structure approach, but in practice
be compact. Sometimes millions of objects of that typically doesn’t happen.
such classes exist, and even with modern memory [5] Writing the basic functions of a concrete
sizes space overheads can be a burden. If nothing type is not difficult, but it is not trivial
else, reading and writing objects with bloated rep- either. For example, adding a year to a
resentations can be a nuisance. date requires us to handle leap years. By
The use of concrete types must be fast. In my relying on common access functions, we
world at least, programmers are prone to represent eventually achieve an implementation that
something as plain data structure out of fear of has been better thought out and has fewer
overheads supposedly associated with abstrac- errors.
tions. [6] Since more of the implementation is docu-
There are no time or space overheads associ- mented and shared, user code becomes
ated with the Date class as defined above. The more uniform. Thus, code written by oth-
size is identical to that of the plain date struc- ers become easier to comprehend.
ture, and inlining is done for simple member These are classical reuse benefits and I don’t
functions to make these as fast as the code a pro- think we should decline them just because they
grammer would write accessing a plain structure are easy to obtain.
directly.
Often, it is important that simple concrete 6.2.3 Re-using Concrete Types
types, such as Date, be layout-compatible with For many concrete types, derivation doesn’t make
simple data structures, such as date, as used in sense. Consider, deriving a new class from
traditional languages. This allows simple Date:
exchange or sharing of information with code class MyDate : public Date {
written in traditional languages. This can be a // ...
major convenience if your operating system, your };
database, or your high-performance numeric
library is written in a traditional language and Is it ever valid for MyDate to be used as a plain
requires manipulation of data of a specific layout. Date? Well, that depends on what MyDate is,
The Date class is very simple and very basic. but in my experience it is rare to find a concrete
It requires no elaborate framework, no class hier- type that makes a good base class without modifi-
archies, no clever dispatcher to mediate access, cation.
etc. It doesn’t affect the overall structure of a pro- Derivation from a concrete type is almost
gram much; it just provides a lot of help at the always a mistake. A concrete type is a self-
detailed programming level – below the level of contained entity that can’t easily added to in a
detail of interest to most managers and to many way that makes sense. A concrete type is ‘‘re-
designers. used’’ unmodified in the same way as built-in
If such types are that simple, why bother types such as int are. For example:
spending time on them? class Date_and_time {
[1] The concepts best represented by such public:
simple types are common; most applica- // ...
tions can use a few dozen or a few hundred private:
Date d;
such types. Thus, any benefits we get Time t;
from a single concrete type, we get many };
times over.
[2] The problems relating to lack of encapsu- This form of use (reuse?) is usually simple, effec-
lation of plain structures (§6.2.1) are elimi- tive, and efficient.
nated. Maybe it was a mistake not to design Date to
[3] The replication of effort writing simple be easy to modify through derivation? It is some-
access functions is eliminated. times asserted that every class should be open to
[4] Making a concrete type the subject of a modification by overriding and by access from
derived class member functions. This view leads
-7-

to a variant of Date along these lines: For example:


class Date2 { class Date3 {
public: public:
// public interface, consisting // public interface, consisting
// primarily of virtual functions // primarily of virtual functions
protected: protected:
// representation and other Date d;
// implementation details };
};
Here, the functions are declared virtual, mean- 6.3 Namespaces
ing that a class derived from Date2 (in the style Class hierarchies express (hierarchical) relation-
of MyDate above) can provide its own versions. ships, but not every relationship in a program can
To make it possible to write such overriding func- or should be expressed as a hierarchical relation-
tions easily and efficiently, the representation is ship between classes. For example, if a class is
declared protected. A protected member intented for use only in the context of another
of a class is accessible not just to the classes’ own class it can be declared a member of that class
members, but also to the member functions of exactly the way a function can be:
derived classes.
class Date {
This achieves the objective of making Date2 public:
arbitrarily mallable by derivation, yet keeping its
user interface unchanged. However, there are enum Month {
costs: jan, feb, mar,
[1] Efficiency of basic operations – a C++ vir- apr, may, jun,
tual function call is a fraction slower than jul, aug, sep,
an ordinary function call, virtual functions oct, nov, dec
};
cannot be inlined as often as non-virtual
functions, and a class with virtual func- // ...
tions typically incurs a one word space };
overhead.
[2] Need to use free store – the aim of Date2 Date::Month m = Date::nov;
is to allow objects of different classes More generally, C++ provides namespaces for
derived from Date2 to be used inter- grouping declarations [Stroustrup,1994]. For
changeably. Because the sizes of these example, many operations on Dates shouldn’t be
derived classes differ, the obvious thing to members of class Date because they don’t need
do is to allocate them on the free store and direct access to the representation of a Date.
access them through pointers or references. Providing such functions as non-member func-
Thus, the use of genuine local variables tions leads to a cleaner Date class, but we would
dramatically decreases. still like to make the association between the
[3] Inconvenience to users – to benefit from functions and the class explicit:
the polymorphism provided by the virtual
functions, accesses to Date2s must be namespace Chrono {
through pointers or references.
// facilities for dealing with time:
Naturally, these costs are not always significant,
and as we will see in §6.4 the behavior of a class enum Month {
defined in this way is often exactly what we want. // ...
However, for a simple concrete type, such as };
Date2, the costs are unnecessary and can be sig-
nificant. class Date {
// ...
Please note that the costs are fundamental; dif-
};
ferent languages present the facilities differently,
but every language that provides run-time poly-
morphism incur these costs in some way or other.
Finally, a well-designed concrete type is often
the ideal representation for a more mallable type.
-8-

int diff(Date a, Date b); I use the dotted lines to show that private
bool leapyear(int y); inheritance is an implementation issue that does
Date next_weekday(Date d); not affect the interface of the derived class.
Date next_saturday(Date d); Importantly, a common interface (here, set)
can be provided long after the design and imple-
// ... mentation of implementation classes (here,
} vector and list). I find that when people
A namespace is not a module; it is not an object. design things, they typically first invent some-
A namespace is a general scope mechanism to thing fairly concrete. They design an array, they
support a variety of techniques related to modu- invent a list, and only later do they discover an
larity. Not incidentally, namespaces provides a abstraction that covers both in a given context.
way of avoiding name clashes in software com- Using abstract classes as shown above, we use
posed out of libraries from different suppliers. (re-use?) vector and list without the fore-
For example: sight (and cost) necessary to design them as part
of a common hierarchy.
namespace LibA {
class String {
As a matter of fact, you can do this ‘‘late
// A-style string abstraction’’ several times. Say, I want to repre-
}; sent the notion of ‘‘something you could read
// ... from.’’ This is a very different abstraction from
} set, yet I can provide such an interface to arbi-
trary sets as well as for lists, vectors, files, and
namespace LibB { input streams much in the way I provided set as
class String { an interface to vector and list.
// B-style string
};
Late abstraction using abstract classes allows
// ... us to provide different implementations of a con-
} cept even when there is no significant similarity
between the implementations.
LibA::String s1 = "Nicholas";
LibB::String s2 = "Annemarie"; 6.5 Classical Hierarchies
Sometimes we do have sufficient foresight to
6.4 Abstract Classes design a classical hierarchy. More importantly,
It is possible to completely disassociate imple- sometimes the various implementations of a con-
mentation and interface. For example, we might cept have a high degree of commonality so that
implement a set using either an array or a list in there is significant benefit in organizing these
such a way that the two kinds of sets can be used implementations into a hierarchy. For example,
interchangeably: consider a class hierarchy that one might find in
an application relying on a windows system:
class set {
// ... window
};

class v_set : public set, dial slider


private vector {
// ...
ival_dial ival_slider
};
Presumably, the implementations of the applica-
class l_set : public set, tion classes ival_dial and ival_slider
private list {
are greatly facilitated by code and data provided
// ...
}; by the ‘‘system classes’’ window, dial, and
slider. That is, you build your code incre-
or graphically: mently and your interfaces incrementally.
vector
. set .list
.. ..
.. .
.. ..
. ..
v_set l_set
-9-

6.6 Hierarchies and Abstract Classes class BB_ival_slider


A classical hierarchy is a nice way of providing a : public ival_slider,
variety of related concepts and a nice way of min- protected BB_slider {
imizing the effort of building their implementa- public:
tions. However, you do get the classes in the // functions overriding ival_slider
hierarchy tightly coupled. If anything significant // functions as needed to implement
in a base class changes, all of the derived classes // the application concepts
protected:
must change (or at least be recompiled) to match. // functions overriding BB_slider
In particular, any significant change to ‘‘system // and BB_window functions as
classes’’ at the base of a hierarchy, such as // required to conform to user
window, will affect application classes, such as // interface standards
ival_dial. Worse, the choice of a foundation private:
library representing system resources determines // representation and other
the structure of the application class hierarchy and // implementation details
};
permeates the application code.
There are quite a few ways of dealing with This structure assumes that details of what is to be
this. For example, some languages have a solu- displayed by a windows system is expressed by
tion (at its associated costs) mandated, and some overriding virtual functions in the BB_windows
implementations of C++ allow major changes to hierarchy. This may not be the ideal organization
base classes without requiring re-compilation of of a user interface system, but it is not uncom-
derived classes. However, here I’ll show a solu- mon.
tion using abstract classes to make dependencies I use protected members and protected inheri-
explicit. Logically, it closely parallels the way tance to allow classes derived from
the abstract class set was used to insulate users BB_ival_slider to use information about its
from the details of vectors and lists. implementation.
Here, an application hierarchy
6.7 Generic Programming
ival_box
A major theme in the C++ community over the
last few years has been the development of tech-
ival_dial ival_slider niques exploiting the template mechanism.
is written independently of implementation details
and then later tied into an implementation hierar- 6.7.1 Parameterization
chy without affecting the users of the application Independent concepts should be independently
hierarchy: represented and should be combined only when
needed.
BB_window ival_box BB_window Where this principle is violated, you either
bundle unrelated concepts together or create
ival_dial ival_slider unnecessary dependencies in the implementation
of classes and functions. In particular, fitting
weakly related class into a single hierarchy can be
BB_knob BB_slider a source of unnecessary and problem-causing
dependencies.
BB_ival_dial BB_ival_slider Consider the concepts of sorting, character,
string, and collating sequence. A sort algorithm is
This expresses the design in such a way that the independent from the concept of a character. The
application code becomes independent of any concept of a string is independent of any particu-
change in the implementation hierarchy. lar kind of a character. Finally, the collating
I have used the BB prefix for realism; suppli- sequence which you use when you sort strings of
ers of major libraries invariably prepend some characters is independent of these other three con-
identifying initials. In the future, I expect names- cepts.
paces (§6.3) to be used instead. This independence can be expressed directly.
The declaration of a class that ties an applica- Here is a string parameterized by the kind of char-
tion class to the implementation hierarchy will acters contained so that we can make strings of
look something like this: both built-in and user-defined character types:
- 10 -

template<class C> cmp(s1,s2);


class string { cmp(js1,js2);
// ... cmp(us1,us2)
}; cmp<char,no_case>(s1,s2);

class Jchar { Here, no_case is a collator defining eq() and


// Japanese characters lt() not to be case sensitive.
}; Typically, the string class, the cmp()
function, the collator classes, and the character
string<char> s1, s2; classes will be written by different people. Only
the final user puts all of the independently devel-
string<unsigned char> us1, us2;
oped pieces together.
string<Jchar> js1, js2; This style of design relying on templates and
additional template arguments (in this example,
Independently, we can define the notion of a col- Coll) to express policies, is the basis of much of
lating sequence and a string comparison function: the C++ standard library. The result is excep-
template<class C> tional flexibility and unsurpassed run-time effi-
class std_coll { ciency.
public:
bool eq(C a, C b) 6.7.2 Containers and Algorithms
{ return a==b; } I want to have algorithms written once and used
bool lt(C a, C b)
{ return a<b; }
for objects of many different types. I want these
}; algorithms to run as fast as functions written for a
single argument type. I want this to be compile-
template< time checked so that I can be more confident of
class C, my code. I don’t want to be forced to fit my types
class Coll = std_coll<C> into a hierarchy simply to be able to use them for
> the generic algorithms.
int cmp( The containers and algorithms in the C++
string<C>& s1,
string<C>& s2
standard library use a variant of the philosophy of
) keeping independent concepts separate. Much of
{ the library is based on the notion of a of sequence.
// compare s1 with s2 Examples of sequences are arrays, sets, lists,
// using Coll::eq and Coll::lt maps, files.
// to do character comparisons A sequence has a beginning and an end. The
} end is one beyond the last element of the
The cmp template function takes two template sequence. Positions in a sequence are represented
arguments: by iterators.
– the type of characters in the strings, and begin end
– the collator supplying the character com- | |
parison operations. v v
The ability to pass operations as template parame- XXX -> .... -> XXX -> 0
ters is a very powerful expressive mechanism. It Given an iterator for an element of a sequence, we
is also important for efficiency. For example, it is can get to the next element using the ++ (incre-
trivial for a compiler to inline all uses of eq() ment) operator. Given an iterator for an element,
and lt(). This can be a significant advantage we can access the element itself using the *
compared to C where operations can only be (dereference) operator.
passed as pointers to functions so that function Given this simple notion, a surprising number
call overheads are incurred. of useful algorithms can be expressed. For exam-
The second template paramenter has a default ple, this template function writes all elements of a
so we need only specify it if we want a non- container to output:
standard collating sequence. The first template
parameter can usually be deduced from the argu-
ments to cmp(). For example:
- 11 -

template<class C> In addition to facilities that support object-


void print(C& s) oriented programming, I want – and C++ pro-
{ vides – features that go beyond those in their sup-
C::iterator p=[Link](); port for direct expression of concepts and rela-
tionships.
while ( p!=[Link]() ) { Several of the themes related to C++ program-
cout << *p; // output ming style in this paper have been developed fur-
p++; // next
}
ther in [Koenig,1995b]. The design and evolution
} of C++, including its most recent features, is dis-
cussed in [Stroustrup,1994].
The C++ standard library containers and algo-
rithms are primarily the work of Alex Stepanov. 8 Acknowledgements
A surprising number of containers and algorithms
can be expressed using just a few kinds of itera- Thanks to the OOPSLA’95 program committee
tors. Importantly, the resulting generic algorithms for inviting me to give the talk upon which this
are efficient even compared to hand-crafted paper is based, and especially to May Loomis for
assembly code. For example, the C++ standard encouraging me to get this paper written. Carolyn
library algorithm, sort() is for many simple Heaps transcribed the audio tape of my talk to
and realistic examples several times faster than produce the first draft of this paper. Tim Griffin
the C standard library qsort() function. For and Christos Polyzois made many constructive
more information about the C++ standard library comments.
and the principles underlying its design see
[Koenig,1995] [Stepanov,1994]. 9 References
[Koenig,1995] Andrew Koenig (editor): Draft
7 Closing Remarks Proposed International Standard for Infor-
Are the various facilities presented above object- mation Systems – Programming Language
oriented or not? Which ones? Using what defini- C++. ANSI Standards Secretariat.
tion of object-oriented? CBEMA, 1250 Eye Street NW, Suite 200,
In most contexts, I think these are the wrong Washington DC20005, USA. 1995.
questions. What matters is what ideas you can [Koenig,1995b] Andrew Koenig and Bjarne
express clearly, how easily you can combine soft- Stroustrup: A Foundation for Native C++
ware from different sources, and how efficient Styles. Software – Practice & Experience.
and maintainable the resulting programs are. In To appear 1995.
other words, how you support good programming [Stepanov,1994] Alexander Stepanov and
techniques and good design techniques matters Meng Lee: The Standard Template
more than labels and buzz words. Library. ISO Programming language C++
The fundamental idea is simply to improve project. Doc No: X3J16/94-0095,
design and programming through abstraction. WG21/N0482. May 1994.
You want to hide details, you want to exploit any [Stroustrup,1991] Bjarne Stroustrup: The C++
commonality in a system, and you want to make Programming Language. Addison-
this affordable. Wesley. 1991.
I would like to encourage you not to make [Stroustrup,1994] Bjarne Stroustrup: The
object-oriented a meaningless term. The notion Design and Evolution of C++. Addison-
of ‘‘object-oriented’’ is too frequently debased Wesley. 1994.
– by equating it with good,
– by equating it with a single language, or
– by accepting everything as object-oriented.
I have argued that there are – and must be – use-
ful techniques beyond object-oriented program-
ming and design. However, to avoid being totally
misunderstood, I would like to emphasize that I
wouldn’t attempt a serious project using a pro-
gramming language that didn’t at least support the
classical notion of object-oriented programming.

Common questions

Powered by AI

Stroustrup views the support for multiple programming styles in C++ as a major strength because it allows programmers flexibility in choosing the most appropriate method for problem-solving. C++ supports traditional C-style programming, abstract classes, and generic programming among others, thus enabling it to cater to various needs and situations in system design and implementation .

Stroustrup differentiates classical programming languages from object-oriented ones by noting that the latter support abstraction, inheritance, and run-time polymorphism. Classical languages like C, Fortran4, and Pascal lack classes, while languages like Ada95, Beta, C++, and Smalltalk meet these criteria, making them object-oriented .

Namespaces in C++ group declarations, helping avoid name clashes and supporting modularity by allowing related functions and classes to be organized logically. They allow for explicit association between functions and classes without the need for those functions to be class members, enhancing code clarity and structure .

Stroustrup suggests using non-virtual functions in concrete classes like Date for efficiency, while reserving inheritance for situations that require flexibility, like Date2 with virtual functions for polymorphic behavior. He cautions against unnecessary extensibility for simple types due to associated costs, proposing that classes should be designed to balance direct use and potential extension effectively .

Stroustrup argues that concrete classes can remedy issues by encapsulating data, providing initialization through constructors, offering non-modifying access functions, and allowing copy operations. This design prevents direct manipulation of data structure details and ensures operations are contextually appropriate and efficient .

Stroustrup considers a broad definition important to avoid exclusions and bias, advocating for object-oriented to encompass abstraction (classes and objects), inheritance (building on existing abstractions), and run-time polymorphism (run-time binding). This approach ensures inclusion of major languages like Ada95, Beta, C++, and others while excluding those without necessary features .

Stroustrup suggests that to evaluate object-oriented programming techniques, one must identify specific benefits and risks associated with their use. This involves a practical understanding of what object-oriented entails and comparison with alternative techniques, as opposed to vague or ill-defined promises .

Stroustrup identifies costs of run-time polymorphism as efficiency overheads (e.g., slower virtual function calls, increased use of free store), complexity for users (e.g., requirement to use pointers/references), and potential decreases in local variable usage. These factors can make such polymorphism impractical for simple types, affecting the design choices of programmers .

A useful and intellectually honest definition of 'object-oriented' must not be a mere synonym for 'good,' should not exclude most accepted meanings, and must have a firm historical basis. Additionally, the definition must exclude something, meaning not everything good is object-oriented, and not everything object-oriented is good .

Misuse of 'object-oriented' implies equating the term with 'good' without basis, leading to confusion and bad programming practices. Stroustrup notes that programs deemed object-oriented can still be poorly designed, hard to understand, and maintain, suggesting that a precise definition and discrimination between different methods is necessary .

You might also like