12.2 Namespaces

What’s in a name? That which we call a rose By any other name would smell as sweet.

WILLIAM SHAKESPEARE, Romeo and Juliet

When a program uses different classes and functions written by different programmers, there is a possibility that two programmers will use the same name for two different things. Namespaces are a way to deal with this problem. A namespace is a collection of name definitions, such as class definitions and variable declarations.

Namespaces and using Directives

We have already been using the namespace that is named std. The std namespace contains all the names defined in the standard library files (such as iostream and cstdlib) that you use. For example, when you place the following at the start of a file,

#include <iostream>

that places all of the name definitions (for names like cin and cout) into the std namespace. Your program does not know about names in the std namespace unless you specify that it is using the std namespace. So far, the only way we know how to specify the std namespace (or any namespace) is with the following sort of using directive:

using namespace std;

A good way to see why you might want to include this using directive is to think about why you might want to not include it. If you do not include this using directive for the namespace std, then you can define cin and cout to have some meaning other than their standard meaning. (Perhaps you want to redefine cin and cout because you want them to behave a bit differently from the standard versions.) Their standard meaning is in the std namespace, and without the using directive (or something like it), your code knows nothing about the std namespace, and therefore, as far as your code is concerned, the only definitions of cin and cout are whatever definitions you give them.

Every bit of code you write is in some namespace. If you do not place the code in some specific namespace, then the code is in a namespace known as the global namespace. So far, we have not placed any code we wrote in any namespace, so all of our code has been in the global namespace. The global namespace does not have a using directive because you are always using the global namespace. You could say that there is always an implicit automatic using directive that says you are using the global namespace.

Note that you can be using more than one namespace at the same time. For example, we are always using the global namespace and we are usually using the std namespace. What happens if a name is defined in two namespaces and you are using both namespaces? This results in an error (either a compiler error or a run-time error, depending on the exact details). You can have the same name defined in two different namespaces, but if that is true, then you can only use one of those namespaces at a time.1 However, this does not mean you cannot use the two namespaces in the same program. You can use them each at different times in the same program.

For example, suppose ns1 and ns2 are two namespaces, and suppose myFunction is a void function with no arguments that is defined in both namespaces but defined in different ways in the two namespaces. The following is then legal:

{
    using namespace ns1;
    myFunction( );
}
{
    using namespace ns2;
    myFunction( );
}

The first invocation would use the definition of myFunction given in the namespace ns1, and the second invocation would use the definition of myFunction given in the namespace ns2.

Recall that a block is a list of statements, declarations, and possibly other code, enclosed in braces {}. A using directive at the start of a block applies only to that block. So the first using directive applies only in the first block, and the second using directive applies only in the second block. The usual way of phrasing this is to say that the scope of the ns1 namespace is the first block, while the scope of the ns2 namespace is the second block. Note that because of this scope rule, we are able to use two conflicting namespaces in the same program (such as in a program that contains the two blocks we discussed in the previous paragraph).

When you use a using directive in a block, it is typically the block consisting of the body of a function definition. If you place a using directive at the start of a file (as we have usually done so far), then the using directive applies to the entire file. A using directive should normally be placed near the start of a file or the start of a block.

Creating a Namespace

In order to place some code in a namespace, you simply place it in a namespace grouping of the following form:

namespace NameSpaceName
{
    SomeCode
}

When you include one of these groupings in your code, you are said to place the names defined in SomeCode into the namespace NameSpaceName. These names (really the definitions of these names) can be made available with the using directive:

using namespace NameSpaceName;

For example, the following, taken from Display 12.5, places a function declaration in the namespace savitch1:

Display 12.5 Namespace Demonstration


An illustration shows a code segment for demonstrating a “Namespace.”

Sample Dialogue

Greetings from namespace savitch2.
Hello from namespace savitch1.
A Big Global Hello!
namespace savitch1
{
    void greeting( );
}

If you look again at Display 12.5, you see that the definition of the function greeting is also placed in namespace savitch1. That is done with the following additional namespace grouping:

namespace savitch1
{
    void greeting( )
    {
        cout << "Hello from namespace savitch1.\n";
    }
}

Note that you can have any number of these namespace groupings for a single namespace. In Display 12.5, we used two namespace groupings for namespace savitch1 and two other groupings for namespace savitch2.

Every name defined in a namespace is available inside the namespace grouping, but the names can be also be made available to code outside of the namespace. That function declaration and function definition in the namespace savitch1 can be made available with the using directive:

using namespace savitch1;

as illustrated in Display 12.5.

Self-Test Exercises

  1. Consider the program shown in Display 12.5. Could we use the name greeting in place of bigGreeting?

  2. In Self-Test Exercise 7, we saw that you could not add a definition for the following function (to the global namespace):

    void greeting( );

    Can you add a definition for the following function declaration to the global namespace?

    void greeting(int howMany);
  3. Can a namespace have more than one namespace grouping?

Qualifying Names

Suppose you are faced with the following situation: You have two namespaces, ns1 and ns2. You want to use the function fun1 defined in ns1 and the function fun2 defined in namespace ns2. The complication is that both ns1 and ns2 define a function myFunction. (Assume all functions in this discussion take no arguments, so overloading does not apply.) It would not be a good idea to use the following:

using namespace ns1;
using namespace ns2;

This would provide conflicting definitions for myFunction.

What you need is a way to say you are using fun1 in namespace ns1 and fun2 in namespace ns2 and nothing else in the namespaces ns1 and ns2. The following are called using declarations, and they are your answer:

using ns1::fun1;
using ns2::fun2;

A using declaration of the form

using NameSpace::OneName

makes (the definition of) the name OneName from the namespace NameSpace available, but does not make any other names in NameSpace available.

Note that you have seen the scope resolution operator, ::, before. For example, in Display 12.2 we had the following function definition:

void DigitalTime::advance(int hoursAdded, int minutesAdded)
{
    hour = (hour + hoursAdded) % 24;
    advance(minutesAdded);
}

In this case the :: means that we are defining the function advance for the class DigitalTime, as opposed to any other function named advance in any other class. Similarly,

using ns1::fun1;

means we are using the function named fun1 as defined in the namespace ns1, as opposed to any other definition of fun1 in any other namespace.

Now suppose that you intend to use the name fun1 as defined in the namespace ns1, but you intend to use it only one time (or a small number of times). You can then name the function (or other item) using the name of the namespace and the scope resolution operator as in the following:

ns1::fun1( );

This form is often used when specifying a parameter type. For example, consider

int getNumber(std::istream inputStream)
. . .

In the function getNumber, the parameter inputStream is of type istream, where istream is defined as in the std namespace. If this use of the type name istream is the only name you need from the std namespace (or if all the names you need are similarly qualified with std::), then you do not need

using namespace std;

A Subtle Point About Namespaces (Optional)

There are two differences between a using declaration, such as

using std::cout;

and a using directive, such as

using namespace std;

The differences are as follows:

  1. A using declaration (like using std::cout;) makes only one name in the namespace available to your code, while a using directive (like using namespace std;) makes all the names in a namespace available.

  2. A using declaration introduces a name (like cout) into your code so that no other use of the name can be made. However, a using directive only potentially introduces the names in the namespace.

Point 1 is pretty obvious. Point 2 has some subtleties. For example, suppose the namespaces ns1 and ns2 both provide definitions for myFunction but have no other name conflicts. Then the following will produce no problems:

using namespace ns1;
using namespace ns2;

provided that (within the scope of these directives) the conflicting name myFunction is never used in your code. On the other hand, the following is illegal, even if the function myFunction is never used:

using ns1::myFunction;
using ns2::myFunction;

Sometimes this subtle point can be important, but it does not impinge on most routine code.

Self-Test Exercises

  1. Write the function declaration for a void function named wow. The function wow has two parameters, the first of type speed as defined in the speedway namespace and the second of type speed as defined in the indy500 namespace.

  2. Consider the following function declarations from the definition of the class Money in Display 11.4.

    void input(istream& ins);
    void output(ostream& outs) const;

    Rewrite these function declarations so that they do not need to be preceded by

    using namespace std;

    (You do not need to look back at Display 11.4 to do this.)

Unnamed Namespaces

Our definition of the class DigitalTime in Displays 12.1 and 12.2 used three helping functions: digitToInt, readHour, and readMinute. These helping functions are part of the implementation for the ADT class DigitalTime, so we placed their definitions in the implementation file (Display 12.2). However, this does not really hide these three functions. We would like these functions to be local to the implementation file for the class DigitalTime. However, as we have done it, they are not. In particular, we cannot define another function with the name digitToInt (or readHour or readMinute) in an application program that uses the class DigitalTime. This violates the principle of information hiding. To truly hide these helping functions and make them local to the implementation file for DigitalTime, we need to place them in a special namespace called the unnamed namespace.

A compilation unit is a file, such as a class implementation file, along with all the files that are #included in the file, such as the interface header file for the class. Every compilation unit has an unnamed namespace. A namespace grouping for the unnamed namespace is written in the same way as any other namespace, but no name is given, as in the following example:

namespace
{
    void sampleFunction( )
       .
       .
       .
} //unnamed namespace

All the names defined in the unnamed namespace are local to the compilation unit, and thus the names can be reused for something else outside the compilation unit. For example, Displays 12.6 and 12.7 show a rewritten (and our final) version of the interface and implementation file for the class DigitalTime. Note that the helping functions (readHour, readMinute, and digitToInt) are all in the unnamed namespace and therefore are local to the compilation unit. As illustrated in Display 12.8, the names in the unnamed namespace can be reused for something else outside the compilation unit. In Display 12.8 the function name readHour is reused for another different function in the application program.

Display 12.6 Placing a Class in a Namespace—Header File

An illustration shows a code segment illustrating how to place a “Class” in a “Namespace–Header File.”

Display 12.7 Placing a Class in a Namespace—Implementation File

An illustration shows a code segment illustrating how to place a “Class” in a “Namespace–Implementation File.”
An illustration shows the continued part of the code segment illustrating how to place a “Class” in a ”Namespace–Implementation File.“

Display 12.8 Placing a Class in a Namespace—Application Program

An illustration shows a code segment illustrating how to place a “Class” in a “Namespace–Application Program.”

Sample Dialogue

Let's play a time game.
Let's pretend the hour has just changed.
You may write midnight as either 0 or 24,
but I will always write it as 0.
Enter the hour as a number (0 to 24): 11
You entered 11:00
15 minutes later the time will be 11:15
2 hours and 15 minutes after that
the time will be 13:30

If you look again at the implementation file in Display 12.8, you will see that the helping functions digitToInt, readHour, and readMinute are used outside the unnamed namespace without any namespace qualifier. Any name defined in the unnamed namespace can be used without qualification anywhere in the compilation unit. (Of course, this needed to be so, since the unnamed namespace has no name to use for qualifying its names.)

It is interesting to note how unnamed namespaces interact with the C++ rule that you cannot have two definitions of a name (in the same namespace). There is one unnamed namespace in each compilation unit. It is easily possible for compilation units to overlap. For example, both the implementation file for a class and an application program using the class would normally include the header file (interface file) for the class. Thus, the header file is in two compilation units and hence participates in two unnamed namespaces. As dangerous as this sounds, it will normally produce no problems as long as each compilation unit’s namespace makes sense when considered by itself. For example, if a name is defined in the unnamed namespace in the header file, it cannot be defined again in the unnamed namespace in either the implementation file or the application file. So, a name conflict is avoided.

Programming Tip Choosing a Name for a Namespace

It is a good idea to include your last name or some other unique string in the names of your namespaces so as to reduce the chance that somebody else will use the same namespace name as you do. With multiple programmers writing code for the same project, it is important that namespaces that are meant to be distinct really do have distinct names. Otherwise, you can easily have multiple definitions of the same names in the same scope. That is why we included the name savitch in the namespace dtimesavitch in Display 12.7.

Self-Test Exercises

  1. Would the program in Display 12.8 behave any differently if you replaced the using directive

    using namespace dtimesavitch;
    with the following using declaration?
    using dtimesavitch::DigitalTime;
  2. What is the output produced by the following program?

    #include <iostream> using namespace std;
    namespace sally
    {
        void message( );
    }
    namespace
    {
        void message( );
    }
    int main( )
    {
        {
            message( );
            using sally::message;
            message( );
        }
        message( );
        return 0;
    } namespace sally
    {
        void message( )
        {
            cout << "Hello from Sally.\n";
        }
    } namespace
    {
        void message( )
        {
            cout << "Hello from unnamed.\n";
        }
    }
  3. In Display 12.7 there are two groupings for the unnamed namespace: one for the helping function declarations and one for the helping function definitions. Can we eliminate the grouping for the helping function declarations? If so, how can we do it?