web analytics

Understanding Namespace in C++

Options

davegate 143 - 921
@2015-12-18 10:16:44

What is Namespace?

A program includes many identifiers defined in different scopes. Sometimes a variable of one scope will "overlap" (i.e., collide) with a variable of the same name in a different scope, possibly creating a naming conflict. The C++ standard attempts to solve this problem with namespaces. Each namespace defines a scope in which identifiers and variables are placed. To use a namespace member, either the member's name must be qualified with the namespace name and the binary scope resolution operator (::), as in

MyNameSpace::member

or a using declaration or using directive must appear before the name is used in the program. Typically, such using statements are placed at the beginning of the file in which members of the namespace are used. For example, placing the following using directive at the beginning of a source-code file

using namespace MyNameSpace;

specifies that members of namespace MyNameSpace can be used in the file without preceding each member with MyNameSpace and the scope resolution operator (::).

A using declaration (e.g., using std::cout;) brings one name into the scope where the declaration appears. A using directive (e.g., using namespace std;) brings all the names from the specified namespace into the scope where the directive appears.

@2015-12-18 10:26:57

What happens if two namespaces contain the same name?

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.

namespace A {
  int x = 1;
  int z = 2;
}

namespace B {
  int y = 3;
  int z = 4;
}
void doSomethingWith(int i) throw();

void sample() throw()
{
  using namespace A;                                 <-- 1
  using namespace B;                                 <-- 2

  doSomethingWith( x );                              <-- 3
  doSomethingWith( y );                              <-- 4
  doSomethingWith( A::z );                           <-- 5
  doSomethingWith( B::z );                           <-- 6

  #ifdef GENERATE_ERROR
    doSomethingWith( z );                            <-- 7
  #endif
}
main()
{
 sample(); 
}

(1) OK: Introduces A::x and A::z
(2) OK: Introduces B::y and B::z

(3) OK: Unqualified x unambiguously resolves to A::x
(4) OK: Unqualified y unambiguously resolves to B::y

(5) OK: The A:: qualifications makes this unambiguous
(6) OK: The B:: qualifications makes this unambiguous

(7) Error: Ambiguous: A::z or B::z?
@2015-12-18 10:38:43

Using the std Namespace

The contents of header file <iostream> are all defined as part of namespace std. The following code informs the compiler that namespace std is being used.

#include <iostream>

using namespace std; // use std namespace

The using namespace directive specifies that the members of a namespace will be used frequently throughout a program. This allows the programmer to access all the members of the namespace and to write more concise statements such as

cout << "double1 = " << double1 << endl;

Without the using namespace directive, either cout and endl would have to be qualified with std:: such as

std::cout << "double1 = " << double1 << std::endl;

Or individual using declarations must be included for cout and endl as in:

using std::cout;
using std::endl;

A lot of C++ programmers consider it poor practice to write a using directive like the following:

using namespace std;

Because the entire contents of the namespace are included, thus increasing the likelihood of a naming conflict.

@2015-12-19 11:07:34

Unnamed namespaces

A namespace with no identifier before an opening brace produces an unnamed namespace. Each translation unit may contain its own unique unnamed namespace. The following example demonstrates how unnamed namespaces are useful.

#include <iostream>

using namespace std;

namespace {
   const int i = 4;
   int variable;
   }

int main()
{
   cout << i << endl;
   variable = 100;
   return 0;
}

In the previous example, the unnamed namespace permits access to i and variable without using a scope resolution operator.

The following example illustrates an improper use of unnamed namespaces.

#include <iostream>

using namespace std;

namespace {
   const int i = 4;
   }

int i = 2;

int main()
{
   cout << i << endl; // error
   return 0;
}

Inside main, i causes an error because the compiler cannot distinguish between the global name and the unnamed namespace member with the same name. In order for the previous example to work, the namespace must be uniquely identified with an identifier and i must specify the namespace it is using.

You can extend an unnamed namespace within the same translation unit. For example:

#include <iostream>

using namespace std;

namespace {
   int variable;
   void funct (int);
   }

namespace {
   void funct (int i) { cout << i << endl; }
   }

int main()
{
   funct(variable);
   return 0;
}

both the prototype and definition for funct are members of the same unnamed namespace.

Comments

You must Sign In to comment on this topic.


© 2024 Digcode.com