Chapter 15. Namespaces

FAQ 15.01 What is the purpose of this chapter?

image

This chapter covers the basic material on namespaces.

The purpose of namespaces is to reduce the number of name clashes that occur with multiple, independently developed libraries. In the early days of C++, this was not as big a problem because there weren't as many C++ libraries as there are today. This situation changed about the time that the standard template library was formalized, and today the large number of class libraries and frameworks on the market accentuates the need for a mechanism to resolve name conflicts.

The original goal for namespaces was to have an elegant solution that could be explained to the typical developer in ten minutes and that could be implemented by a compiler-writer in two weeks. The problem was a bit more difficult than anticipated, and, like almost every other feature in C++, it has some dark corners that most people should avoid. But the basic ideas of namespaces are technically sound and within the grasp of any professional developer.

FAQ 15.02 What is a namespace?

image

A namespace is a declarative region that can be used to package names, improve program readability, and reduce name clashes in the global namespace. It is an elegant alternative to using prefixes to indicate the sources of names.

At the most basic level, the syntax for namespaces is shown in the following example.

image

Namespaces facilitate building large systems by partitioning names into logical groupings.

Namespaces are “open” and can be added to at different places. For most situations, this incremental approach is probably a better alternative than trying to specify all of the names in one location, and this approach is used heavily in the standard library. However the incremental approach must be used carefully, because the effect is as if the compiler made a single pass and knew about only the names that were part of the namespace the last time the namespace was explicitly introduced into the source file.

Namespaces can be nested if desired. Java has a concept similar to namespaces called packages.

UML expresses namespaces as shown below (they are called packages in UML):

image

FAQ 15.03 How can code outside a namespace use names declared within that namespace?

image

One way to use a declaration from a namespace is, for every occurrence, to use the scope operator :: to prefix the name declared in the namespace with the name of the namespace. For example,

image

Another approach is to to introduce the equivalent of a local name with what is known as a using declaration. The function f() from the previous example could be written as

image

Another approach is called a using directive. Using this idea, the function f() from the previous example could be written as

image

Note that a using directive does not declare any variables; it merely makes names available.

Finally, notice that the global namespace can be thought of as the namespace without an identifier (i.e., ::fred refers to fred in the global namespace).

FAQ 15.04 What happens if two namespaces contain the same name?

image

Suppose two different namespaces have their own versions of class string. Both namespaces can be introduced into the same code fragment without conflict, as long as there are no unqualified references to string. However, if there are unqualified references to string, the compiler issues an error because the unqualified name string is ambiguous. This is illustrated in the following example.

image

FAQ 15.05 What are some of the rules for using namespaces?

image

The following example due to Stroustrup (C++ Programming Language, Third Edition, 1997) illustrates some of the basic ideas.

image

FAQ 15.06 What is name lookup?

image

Name lookup, sometimes known as Koenig lookup, is a clever solution to a difficult problem. Consider the problem of printing a string in the following example.

image

The operator<< that's needed is a non-member function that takes a string as a parameter and is packaged with the string class. How is the compiler supposed to find the proper operator? One approach is to make all the names in the entire standard namespace accessible without qualification (e.g., using namespace std;), but this is an ugly solution that is discussed in FAQ 15.09. An equally ugly alternative is to change sample() to the following:

image

Koenig lookup is a better alternative. It recognizes that non-member functions associated with a parameter class such as string can be thought of as part of an extended public: interface, and there is no harm in having the compiler automatically look for such functions in the same namespace as the parameter class. This is the technique known as name lookup, and it allows the example above to work “as is.” The trick is that a class parameter, in this case string, somehow identifies a namespace, in this case std, and then all the non-member functions that refer to that parameter class are automatically made available. It's a pretty slick idea that usually simplifies life.

FAQ 15.07 What are the tradeoffs between the various techniques for using names from a namespace, particularly the standard namespace?

image

Relying solely on the scope operator leads to programs that are hard to read, particularly for frequently used classes such as string. Clutter is not desirable in programs that have to be maintained.

The using declaration is probably the best solution for most cases, because the developer specifically declares what is intended. But this can be tedious, particularly when pulling names from the standard library.

The using directive is less desirable than the using declaration because it pollutes the global namespace unnecessarily and opens the door for later code breakage. This is because compiler writers and class library providers can add names to the standard namespace, which means that programs that utilize using namespace std; can suddenly fail to compile even though the user has not changed anything.

Despite this, we utilize using namespace std; throughout this book to allow our examples to compile and to allow the reader who has not read this chapter yet to muddle through, but this practice has little to recommend it.

FAQ 15.08 Can namespaces break code?

image

Namespaces can cause code to suddenly not compile without changes by the programmer. The easiest way this can occur is discussed in FAQ 15.09, but that situation involves the conscious use of using directives, so there shouldn't have been any surprises at the consequences. Here's an example that's a little more insidious.

Start with a header that declares a namespace MySubsystem and a class Fred in that namespace. For example, the following might be in file MySubsystem.hpp:

image

Now suppose some user code creates a normal function f() that takes a parameter of type MySubsystem::Fred:

image

Now suppose a revision of MySubsystem.hpp adds a function f(Fred& x) to namespace MySubsystem:

image

Suddenly, there is ambiguity as to which f(x) is needed, and the code will not compile.

There are even more exotic examples, but the main point is that there are several ways ambiguity can creep in, and the programmer has to resolve the conflicts manually. This is not a severe problem because the compiler flags it and it is relatively easy to fix.

FAQ 15.09 Do namespaces have any other applications?

image

Namespaces have cleaned up some old problems in two other ways. First, unnamed namespaces are preferable to the use of static global members and reduce the number of meanings that can be placed on the word “static.” Second, using declarations are now the preferred alternative to access declarations that were used to work around some knotty problems with private inheritance.

FAQ 15.10 How do namespaces solve the problem of long identifiers?

image

There is a simple macro-like solution for the long namespace name problem—

namespace CWLN = CompanyWithLongName;

—which allows the use of either the short or the long form of the name. This solution is known as namespace aliases.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset