Using namespace in C++
C++ Namespace - Part 4
Forward: In this part of the series I explain the details on how to use Namespace in C++.
By: Chrysanthus Date Published: 7 Feb 2013
Introduction
The Using Directive
With the presence of the namespace block, you can declare intended global entities in the global scope or somewhat in the namespace block. Whenever you think there will be conflict of names, declare intended global entities in the namespace block. If you are a member of a team producing an application, then avoid using the global scope, and use a namespace. Otherwise you can use the global scope.
A namespace consists typically of declarations, without definitions (without function definitions, without class descriptions). We can say, in the namespace block, you have member names of entities. You normally use the member names outside the namespace block. You can still use the names inside the namespace block; that is, you can still have definitions and code segments in the namespace block; however, avoid such practice.
Assume, you have typed out your namespace block. You are to use the names of the namespace block, outside and below the block. Where you want to use the namespace names, begin with a statement whose syntax is:
using namespace namespaceName;
Just below this line, you use the names of the namespace without preceding them with the namespace name and scope resolution operator. Read and try the following program:
namespace first
{
int identA = 33;
int identAA = 35;
}
using namespace first;
int anInt = identA;
int theInt = identAA;
int main()
{
int mainInt = identA;
return 0;
}
Note: you can also have a function declaration (prototype) in a namespace. In the above namespace block (first), two entities of fundamental object types are declared with assignments (these are simple definitions though, not really recommended).
Below the statement, “using namespace first;”, the names are used without preceding them with the namespace name and the scope resolution operator. In the main function, the names are also used without the precedence. So, below the using-directive here, right down to the end of the file, the names have been used without the precedence.
Bear in mind here that the using-directive has been used in the global scope. So, the effective scope of the namespace in the above program (file) is: in the block of the namespace and below the using-directive right down to the end of file.
In C++ a block is delimited by curly brackets. The local scope, function scope, class scope, global scope and namespace scope are principally defined as a block. In this section of the tutorial, I am talking about the effect of applying the using-directive in a non-global scope.
Read and try the following program that works (compiles):
namespace first
{
int identA = 33;
int identAA = 35;
}
void fn()
{
using namespace first;
int anInt = identA;
//other statements;
}
int main()
{
fn();
return 0;
}
In the program, the using-directive has been typed in the function block (scope). The names from the namespace can only be applied (used) inside this function scope (block). They cannot be used outside or below the function block. This is because when the using-directive is in a non-global scope, the names can only be effective inside the non-global scope, and not outside the non-global scope.
The following program will not work (will not compile) as an attempt is made to apply the namespace name in global scope while the using-directive statement is in the function scope:
namespace first
{
int identA = 33;
int identAA = 35;
}
void fn()
{
using namespace first;
//other statements;
}
int gInt = identA;
int main()
{
fn();
return 0;
}
If you try this code, it will not compile and you would receive an error message.
The using-directive can be typed anywhere in a line; at the beginning, middle or right end; independent of whether it is in a global or local scope.
Effective scope of a Namespace
Before I continue, remember that a namespace is also a scope. The effective scope of a namespace is within the namespace block, and below the using-directive but within the scope in which the using-directive is.
Note: the global scope (namespace) extends into block scopes (namespaces). That is why if the using-directive is in the global scope, the names of the user-defined namespace would be applied (without preceding namespace name and ::) in the main function, which is a function scope or block scope.
Consecutive using-directives within a Scope
Consider the following code that works:
#include <iostream>
using namespace std;
namespace first
{
int identA = 33;
int identAA = 35;
}
namespace second
{
int identB = 44;
int identBB = 46;
}
using namespace first;
int anInt = identA;
int theInt = identAA;
using namespace second;
int ourInt = identB;
int yourInt = identBB;
int main()
{
cout << identA << "\n";
cout << identB << "\n";
return 0;
}
In the above code, there are three namespaces called “std”, “first” and “second”. Their corresponding using-directives are in the global scope “next” to one another. Below each using-directive, you have corresponding statements (names).
The interest here is to show the implication of having the using-directives this way, in one scope. Every name in a program is of the global namespace (scope). Below “using namespace std;” every name of the std namespace adds to the global namespace. Below “using namespace first;” every name of the first namespace adds to the std namespace and global namespace. Below “using namespace second;” every name of the second namespace adds to the first namespace, the std namespace and the global namespace.
That is the effect of using the using-directives “next” to one another in the same scope: the namespace of the using-directive below, adds to the namespaces above, in the scope. If the above using-directives were in a block scope, the above effect will be effective (applied) only to the block scope. Note: the namespace block, is also a block scope.
With the above using-directive situation, name conflict would still occur, if more than one scope have the same name and are used below the using-directives. The solution is to use the scope resolution operator, ::. This solution is an advantage, but the use of :: means you have to type the namespace name followed by scope resolution operator, each time you need a name from the namespace.
Note: what has just been said above concerning the scope resolution operator, is applicable to the famous “namespace std;”.
Read and try the following code, which is similar to the previous one, but this time the using-directive is not used. The scope resolution operator is used for each name from a non-global namespace. This retyping of “namespaceName::” is a disadvantage.
#include <iostream>
using namespace std;
namespace first
{
int ident = 33;
void fn();
}
namespace second
{
int ident = 44;
void fn();
}
int myInt = first::ident;
int yourInt = second::ident;
void first::fn()
{
cout << myInt;
}
void second::fn()
{
//some statements
}
int main()
{
cout << first::ident << "\n";
first::fn();
return 0;
}
The following code segment is in the above code:
int myInt = first::ident;
int yourInt = second::ident;
Here, the name, ident, is of the first and second namespaces. However, myInt and yourInt are of the global namespaces.
With the use of “namespaceName::” the namespace scope does not really extend outside its block. In a statement that has, “namespaceName::”, the namespace scope reoccurs only in that statement, and not in the portion around the statement. However retying “namespaceName::” is tedious and so is a disadvantage. So “using namespace namespacename” and “namespaceName::” each has its advantage and disadvantage. With “using namespace namespacename” you do not need the preceding “namespaceName::” but you suffer from name conflict. With “namespaceName::” you do not have name conflict but you suffer from retying.
Comment on Global Namespace
You do not need the using-directive to make a name declared in the global namespace to be retyped anywhere below the point of declaration, in the global namespace. Whenever you want a globally declared name below, you just retype the name on its own. We have been doing this all along in this course (volume).
The syntax to use the scope resolution operator the normal way with a namespace is:
X::m
where X is the name of the namespace and x is an identifier entity name in the namespace. There are examples of this above.
If X is the global namespace, then it is omitted, as in the following example:
#include <iostream>
using namespace std;
int theInt = 5;
int main()
{
cout << ::theInt;
return 0;
}
The cout object here, uses “::theInt” of the global namespace.
For the global case, in practice, the scope resolution operator is always omitted, as in the following program:
#include <iostream>
using namespace std;
int theInt = 5;
int main()
{
cout << theInt;
return 0;
}
The omission of “X::” for the global case is what we have been doing.
That is it for this part of the series. We stop here and continue in the next part of the series.
Chrys
Related Courses
C++ CourseRelational Database and Sybase
Windows User Interface
Computer Programmer – A Jack of all Trade – Poem
NEXT