The
ability to package data with functions allows you to create a new data type.
This is often called
encapsulation[22].An
existing data type, like a
float,
has several pieces of data packaged together: an exponent, a mantissa, and a
sign bit. You can tell it to do things: add to another
float
or to an
int,
and so on. It has characteristics and behavior.
The
definition of
Stash
creates a new data type. You can
add( )
and
fetch( )
and
inflate( ).
You create one by saying
Stash
s
,
as you create a
float
by saying
float
f
.
A
Stash
also has characteristics and behavior. Even though it acts like a real,
built-in data type, we refer to it as an
abstract
data type,
perhaps because it allows us to abstract a concept from the problem space into
the solution space. In addition, the C++ compiler treats it like a new data
type, and if you say a function expects a
Stash,
the compiler makes sure you pass a
Stash
to that function. The same level of type checking happens with abstract data
types (sometimes called
user-defined
types)
as with built-in types.
You
can immediately see a difference, however, in the way you perform operations on
objects. You say
object.member_function(arglist).
This is “calling a member function for
an object.” But in object-oriented parlance, this is also referred to as
“sending a message to
an object.” So for a
Stash
s
,
the statement
s.add(&i)
“sends a message to
s”
saying “
add( )
this to yourself.” In
fact, object-oriented programming can be summed up in a single sentence as
“sending messages to objects.” Really, that’s all you do
– create a bunch of objects and send messages to them. The trick, of
course, is figuring out what your objects and messages
are,
but once you accomplish that the implementation in C++ is surprisingly
straightforward.
[22]
You should be aware that this term seems to be the subject of ongoing debate.
Some people use it as defined here; others use it to describe
implementation
hiding
,
discussed in Chapter 2.