The hidden implementation
It is helpful to break up the playing
field into class creators (those who create new
data types) and client
programmers[7]
(the class consumers who use the data types in their applications). The goal of
the client programmer is to collect a toolbox full of classes to use for rapid
application development. The goal of the class creator is to build a class that
exposes only what’s necessary to the client programmer and keeps
everything else hidden. Why? Because if it’s hidden, the client programmer
can’t use it, which means that the class creator can change the hidden
portion at will without worrying about the impact to anyone else. The hidden
portion usually represents the tender insides of an object that could easily be
corrupted by a careless or uninformed client programmer, so hiding the
implementation reduces program bugs. The concept of
implementation hiding cannot be
overemphasized.
In any relationship it’s important
to have boundaries that are respected by all parties involved. When you create a
library, you establish a relationship with the client programmer, who is
also a programmer, but one who is putting together an application by using your
library, possibly to build a bigger library.
If all the members of a class are
available to everyone, then the client programmer can do anything with that
class and there’s no way to enforce rules. Even though you might really
prefer that the client programmer not directly manipulate some of the members of
your class, without access control there’s no way to prevent it.
Everything’s naked to the world.
So the first reason for access control is
to keep client programmers’ hands off portions they shouldn’t touch
– parts that are necessary for the internal machinations of the data type
but not part of the interface that users need in order to solve their particular
problems. This is actually a service to users because they can easily see
what’s important to them and what they can ignore.
The second reason for access control is
to allow the library designer to change the internal workings of the class
without worrying about how it will affect the client programmer. For example,
you might implement a particular class in a simple fashion to ease development,
and then later discover that you need to rewrite it in order to make it run
faster. If the interface and implementation are clearly separated and protected,
you can accomplish this easily and require only a relink by the
user.
C++ uses three explicit keywords to set
the boundaries in a class: public, private, and protected.
Their use and meaning are quite straightforward. These access specifiers
determine
who can use the definitions that follow. public
means the following definitions are available to
everyone. The private keyword, on the other hand,
means that no one can access those definitions except you, the creator of the
type, inside member functions of that type. private is a brick wall
between you and the client programmer. If someone tries to access a
private member, they’ll get a compile-time error.
protected acts just like private, with the
exception that an inheriting class has access to protected members, but
not private members. Inheritance will be introduced
shortly.