Online Book Reader

Home Category

Professional C__ - Marc Gregoire [54]

By Root 1451 0
that the tree data structure should allow only one thread at a time to access or modify the structure, so you incorporate locking into the data structure itself. However, what if you want to use this binary tree in another program that happens to be single-threaded? In that case, the locking is a waste of time, and might require your program to link with libraries that it could otherwise avoid. Even worse, your tree structure might not compile on a different platform because the locking code might not be cross-platform. Note that C++11 includes a multithreading library which includes locking mechanisms as explained in Chapter 22. The solution is to create a class hierarchy (introduced in Chapter 3) in which a thread-safe binary tree is a subclass of a generic binary tree. That way you can use the binary tree superclass in single-threaded programs without incurring the cost of locking unnecessarily. Figure 4-1 shows this hierarchy.

FIGURE 4-1

This strategy works well when there are two logical concepts, such as thread safety and binary trees. It becomes more complicated when there are three or more concepts. For example, suppose you want to provide both an n-ary tree and a binary tree, each of which could be thread-safe or not. Logically, the binary tree is a special-case of an n-ary tree, and so should be a subclass of an n-ary tree. Similarly, thread-safe structures should be subclasses of non-thread-safe structures. You can’t provide these separations with a linear hierarchy. One possibility is to make the thread-safe aspect a mix-in class as shown in Figure 4-2.

FIGURE 4-2

That hierarchy requires you to write five different classes, but the clear separation of functionality is worth the effort.

Use Aggregation to Separate Logical Concepts

Aggregation, discussed in Chapter 3, models the has-a relationship: Objects contain other objects to perform some aspects of their functionality. You can use aggregation to separate unrelated or related but separate functionality when inheritance is not appropriate.

For example, suppose you want to write a Family class to store the members of a family. Obviously, a tree data structure would be ideal for storing this information. Instead of integrating the code for the tree structure in your Family class, you should write a separate Tree class. Your Family class can then contain and use a Tree instance. To use the object-oriented terminology, the Family has-a Tree. With this technique, the tree data structure could be reused more easily in another program.

Eliminate User Interface Dependencies

If your library is a data manipulation library, you want to separate data manipulation from the user interface. This means that for those kinds of libraries you should never assume in which type of user interface the library will be used. As such, do not use cout, cerr, cin, stdout, stderr, or stdin, because if the library is used in the context of a graphical user interface these concepts may make no sense. For example, a Windows GUI-based application normally will not have any form of console I/O. If you think your library will only be used in GUI-based applications, you should still never pop up any kind of message box or other kind of notification to the end user; that is the responsibility of the caller to do. These kinds of dependencies not only result in poor reusability, but they prevent the client code from properly responding to an error, and handling it silently.

Use Templates for Generic Data Structures and Algorithms

C++ has a concept called templates allowing you to create structures that are generic with respect to a type or class. For example, you might have written code for an array of integers. If you subsequently would like an array of doubles, you need to rewrite and replicate all the code to work with doubles. The notion of a template is that the type becomes a parameter to the specification, and you can create a single body of code that can work on any type. Templates allow you to write both data structures and algorithms that work on any types.

The simplest

Return Main Page Previous Page Next Page

®Online Book Reader