What is a namespace?

A namespace is a mechanism for expressing a logical grouping of program declarations and/or definitions, such as variable, function, and class definitions. Since a namespace defines a scope, the usual scope rules apply. Hence, if a name is previously declared in the namespace or in the enclosing scope, it can be used directly. A name from another namespace can be used when qualified by the name of its namespace.

Some facts about C++ namespaces

  1. Namespaces were introduced to prevent name clashes by providing an additional "scoping" mechanism.
  2. Namespaces allow you to give names to sections of code in your program.
  3. Namespaces must be defined at global (file) scope and so, in particular, cannot be placed inside any function, including the main function.
  4. Namespaces can only contain definition statements and additional (nested) namespaces.
  5. A namespace does not have to be "all in one place". That is, portions of a given namespace can appear in different locations, including in different files.
  6. Namespaces can be "aliased", i.e., a short name can be established as the equivalent of a long one, as in
    namespace ShortName = VeryLongNamespaceName;
    
    after which the use of
    ShortName::myVar
    
    is equivalent to using this:
    VeryLongNamespaceName::myVar
    

Defining namespaces

  1. Every compilation unit (i.e., every source code file together with all its included files) has a single unnamed namespace (also called an anonymous namespace), which looks like
    namespace
    {
        // declarations/definitions in here
    }
    
    and behaves as though it were followed by a using-directive. That is, all names declared in this namespace are in potential scope until the end of the declarative region containing the unnamed namespace. But, because the namespace has no name, the names in it cannot be used in any file other than the one containing the unnamed namespace. However, using the unnamed namespace does provide an alternative to the use of static external variables (to hide helper functions for a class in the class implementation file, for example) This used to be a "recommended" alternative, but C++ folks have been rethinking that maybe the use of the static keyword wasn't such a bad idea after all.
  2. On the other hand, when you give a name to a namespace, the syntax is
    namespace NameOfNamespace
    {
        // declarations/definitions in here
    }
    
    and this syntax is repeated, with the same name, for every "piece" of the namespace with that particular name.

Using an entity from a namespace

You can use an entity from a namespace in one of three ways:

  1. Via a using directive, as in
    using namespace Scobey;
      ...
    Menu myMenu;
    DisplayIDInfo(MY_ID_INFO, MY_DESCRIPTION);
    
  2. Full direct qualification of each entity used, as in
    Scobey::Menu myMenu;
    Scobey::DisplayIDInfo(MY_ID_INFO, MY_DESCRIPTION);
    
  3. Via a using declaration, as in
    using Scobey::Menu;
    using Scobey::DisplayIDInfo;
      ...
    Menu myMenu;
    DisplayIDInfo(MY_ID_INFO, MY_DESCRIPTION);
    

Which of these three alternatives should be used?

The using directive (the first of the alternatives listed above) is regarded as somewhat defeatist, since it makes everything in the namespace available, opening you up once again to the possibility of name clashes and the avoidance of this was the reason for introducing namespaces in the first place. Nevertheless, common practice, and one that we will follow, is to use this approach for the the "standard namespace, wherein live all the facilities of the C++ Standard Library", and this is why we see the statement

using namespace std;

at the beginning of so many of our programs.

The second alternative listed above represents the other extreme, and requires that each entity from the namespace be qualified with the name of the namespace.

The third and last alternative, the using declaration, represents a happy medium between those two extremes, and is the alternative we will employ with any namespace other than std, and in particular with the Scobey namespace containing the instructor-supplied utilities package.

A namespace subtlety

Suppose a function f() with the same signature and return type is defined (differently) in each of the two namespaces namespace1 and namespace2. The two using directives

using namespace namespace1;
using namespace namespace2;

will not cause a problem on account of f() unless an attempt is made to actually use f(). On the other hand, the two using declarations

using namespace1::f;
using namespace2::f;

will cause a compiler error, even if no attempt is made to use the function f().