9. Namespaces#

Namespaces allow programmers to organize code into discrete, identifiable sections. They help avoid name clashes, especially when integrating with third-party libraries, by providing a distinct container for identifier names. We’ve already been using the standard namespace, std::. Initially, we used using namespace std; to bring in the entire namespace into our code for convenience, but then we migrated to either including specific objects such as cout with using std::cout or using the namespace identifier std:: wherever cout was located in our code.

Namespaces are containers where identifiers (like class, variable, and function names) reside. Namespaces also create a scope for these identifiers.

To understand namespaces, we also need to understand where items are defined how that affects their scope.

Variables defined -

  • in functions are local variables

  • in classes are member variables

  • elsewhere are global variables

Functions defined -

  • in classes are member functions (methods).

  • elsewhere are global functions.

Namespaces add a layer of disambiguation when items have the same name, but exist in different parts of a system.

9.1. Declaring#

Use the following syntax to declare a namespace.

namespace namespace_name {
    // code declarations
}

9.2. Accessing Namespace Members:#

To access members (variables, functions, classes, etc.) of a namespace, use the scope resolution operator ``::.

9.3. The using Directive:#

The `using`` directive allows you to bring the entire namespace into the current scope. Be cautious with this method as it can lead to name clashes.

using MySpace;

9.4. The using Declaration:#

To introduce specific namespace members, use the `using`` declaration.

using MySpace::myVar;

The following code demonstrates declaring a namespace, MyNamespace, and then different ways of accessing it within main.

 1//filename: namespaces.cpp
 2//complile: g++ -std=c++17 -o namespaces namespaces.cpp
 3//execute: ./namespaces
 4#include <iostream>
 5
 6namespace MySpace {
 7    int myVar = 10;
 8    int alterMyVar() {
 9        return 2 * myVar;
10    }
11}
12
13namespace AnotherSpace {
14    int myVar = 50;
15    int alterMyVar() {
16        return 3 * myVar;
17    }
18}
19
20int main(int argc, char *argv[]) {
21    int myVar = 3;
22
23    std::cout << "main: myVar - " << myVar << "\n";
24    std::cout << "MySpace: myVar - " << MySpace::myVar << "\n";
25    std::cout << "MySpace: calling alterMyVar - " << MySpace::alterMyVar() << "\n";
26
27    {
28        using namespace AnotherSpace;  // this using is limited to the scope of {   }
29        std::cout << "calling alterMyVar in AnotherSpace - " << alterMyVar() << "\n";
30        std::cout << "calling alterMyVar in MySpace - " << MySpace::alterMyVar() << "\n";
31    }
32
33    using namespace MySpace;
34    std::cout << "calling alterMyVar - " << alterMyVar() << "\n";
35
36    // Note that with the same identifier, C++ uses the current scope declaration.
37    std::cout << "myVar - " << myVar << "\n";
38
39    std::cout << "calling alterMyVar in AnotherSpace - " << AnotherSpace::alterMyVar() << "\n";
40
41    return EXIT_SUCCESS;
42}

Note that we can’t use using MyNamespace::myVar; in main as myVar is already declared in the current scope.