What's wrong?
We are remarkably adaptable, even in
situations in which perhaps we shouldn’t adapt. The style of the
CStash library has been a staple for C programmers, but if you look at it
for a while, you might notice that it’s rather . . . awkward. When you use
it, you have to pass the address of the structure to every single function in
the library. When reading the code, the mechanism of the library gets mixed with
the meaning of the function calls, which is confusing when you’re trying
to understand what’s going on.
One of the biggest obstacles, however, to
using libraries in C is the problem of name
clashes. C has a single
name space for functions; that is, when the linker looks
for a function name, it looks in a single master list. In addition, when the
compiler is working on a translation unit, it can work only with a single
function with a given name.
Now suppose you decide to buy two
libraries from two different vendors, and each library has a structure that must
be initialized and cleaned up. Both vendors decided that
initialize( ) and cleanup( ) are good names. If you
include both their header files in a single translation unit, what does the C
compiler do? Fortunately, C gives you an error, telling you there’s a type
mismatch in the two different argument lists of the declared functions. But even
if you don’t include them in the same translation unit, the linker will
still have problems. A good linker will detect that there’s a name clash,
but some linkers take the first function name they find, by searching through
the list of object files in the order you give them in the link list. (This can
even be thought of as a feature because it allows you to replace a library
function with your own version.)
In either event, you can’t use two
C libraries that contain a function with the identical name. To solve this
problem, C library vendors will often prepend a sequence of unique characters to
the beginning of all their function names. So initialize( ) and
cleanup( ) might become CStash_initialize( ) and
CStash_cleanup( ). This is a logical thing to do because it
“decorates” the name of the struct the function works on with
the name of the
function.
Now it’s time to take the first
step toward creating classes in C++. Variable names inside a
struct do not clash with
global variable names. So why not take advantage of this for function names,
when those functions operate on a particular struct? That is, why not
make functions members of
structs?