C++ Namespaces Basics

C++ Taking the Bull by the Horns - Part 22

Chrys Forcha
Introduction
This is part 22 of my series, C++ Taking the Bull by the Horns. In this part of the series, we look at what is called Namespaces in C++.

Note: If you cannot see the code or if you think anything is missing (broken link, image absent), just contact me at forchatrans@yahoo.com. That is, contact me for the slightest problem you have about what you are reading.

A problem
Read and try the following code:

int myInt = 3;
int yourInt = 5;

int herInt = myInt + yourInt;

int main()
{

return 0;
}

The compilation of the above code went well. The execution phase went well. Note that we did not use the cout object. In the above code, you have the initialization of two integers with two identifiers. You have one addition statement, where a third identifier is declared. The main function has only the return zero statement. Just note that I did not use the following two lines in the above code:

#include
using namespace std;

These two lines especially the second one are related to the namespace concept. We shall know their uses later in this tutorial.

Note, a program can never be executed unless it is compiled successfully.

Now, read and try the following code where another identifier is declared (the code will not compile and will issue error message - note the error message issued). The two identifiers have the same name, myInt.

int myInt;

int myInt = 3;
int yourInt = 5;

int herInt = myInt + yourInt;

int main()
{

return 0;
}

The program (code) did not compile and error message was issued. The reason the code did not compile is because you cannot have the more than one identifier with the same name in the same scope. Here we are dealing with the file scope.

Normally, if you write a one-file program you would probably be conscious not to have two identifiers with the same name in the same scope. This problem can arise because many programs are large and are written by different people, each person may write a file. The files are combined with the include directives. I will continue the explanation with one file, before I talk about multiple files and global scope. The explanation with one file is application to multiple files and global scope.

When talking about namespaces, we are talking about identifiers, in a way that you should use them. By the word identifier I am referring to identifiers of fundamental object types, identifiers of derived object types (all sorts), identifiers of classes (see later) and identifiers of functions.

To solve the above conflict with one file or with multiple files, the inventors of C++ came up with the idea of namespaces. It is simple: you are advised to have the identifiers of your code in a block (pair of curly braces). That block is a namespace. The block has a name, which you give. That name is the identifier of the block. That identifier is the name of the namespace. For simplicity we shall have initialization of fundamental objects and declaration of functions in the namespaces below.

The Scope Operator
The scope operator is the operator, :: and it is used with namespaces. Read and try the following code (there is no output):

namespace first
{
int ident1 = 33;
void fn1();
}

namespace second
{
int ident2 = 44;
void fn2();
}

int myInt = first::ident1;
int yourInt = second::ident2;

void first::fn1()
{
//some statements
}

void second::fn2()
{
//some statements
}

int main()
{
first::fn1();
return 0;
}

The above code is OK. It compiles successfully. There is no output because the cout object was not in the code.

There are two namespaces in the above code: one is called first and the other is called second. Inside first, you have the initialization of the identifier, ident1 and the declaration of the function, fn1. Inside the namespace, second, you have the initialization of the identifier, ident2 and the declaration of the function, fn2.

In the above code, in order to use the identifiers from a namespace, you have to use the scope operator. You begin with the name of the namespace, then the scope operator, which is :: then the identifier.

The next two statements after the namespaces above, initialize two new identifiers. The first statement uses the int identifier from the namespace, which is called first. The second statement uses the int identifier, from the namespace, which is called second. Note the use of the scope operators in these two statements.

Below the above two statements, you have the definition of the fn1 function from the namespace, first and the definition of the fn2 function from the namespace second. Note the use and the position of the scope operator in these two definitions. Note the position of the return type at the beginning of each of the definitions. Note the use and position of the namespace function declaration identifier in each of the definitions.

In the main function, the function, fn1 of the namespace, first is called. To call it you start with its namespace identifier, then the scope operator and then the function name with its parentheses. In the above code, namespace identifiers for fundamental objects and for functions have been used in a similar way. All that is one way of using identifiers from namespaces.

Note: the identifiers, myInt and yourInt do not belong to any namespace. Note also that we have not used the lines "#include " and "using namespace std;" in the above code. Their uses will be explained, later in this tutorial.

Each time you want an identifier from a namespace, you may find it tedious to start by typing the name of the namespace first, then the scope operator and finally the identifier. The following section offers a solution. However the solution is not applicable to functions, everything being equal.

The using Keyword
Read and try the following code:

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()
{
int mainInt = identA;
return 0;
}

The above code is OK. No functions are involved here. The syntax to use the using keyword is

using namespace namespaceIdent;

It is not a preprocessor directive. It is a statement that ends with a semicolon. When you use a statement like this at the file scope level, like in the above code, then you can use an identifier from the namespace anywhere below the using statement without the preceding name of the namespace and without the scope operator, even in blocks.

In the above code, after the statement, "using namespace first;" you can use identifiers from the namespace, first. Also, after the statement, "using namespace second;" you can use identifiers from the namespace, second. You can still use identifiers of the namespace, first, after the using statement of the namespace, second. This second approach to namespace can lead to conflicts when you have the same identifier in more than one namespace; this is a disadvantage of the second approach. Now, read through the above code again.

Global Scope
In one file an identifier of file scope is an identifier that is not declared in any block. When files are combine with the include preprocessing directive, the file scope identifiers of the individual files are better seen as global scope identifiers. All what has been said above are also applicable to a resulting file that is made up of combined files, through the include preprocessor directives. We shall demonstrate this with two files. The two files are the code of the above program but with slightly different arrangement of code.

Type the following in your editor:

namespace first
{
int identA = 33;
int identAA = 35;
}

namespace second
{
int identB = 44;
int identBB = 46;
}

Save the resulting document as ns.hh in the include directory (that is in the MinGW directory). The above file is the top part of the previous code.

Now type the following in a text editor:

#include
using namespace first;
using namespace second;

int anInt = identA;
int theInt = identAA;

int ourInt = identB;
int yourInt = identBB;

int main()
{
int mainInt = identA;
return 0;
}

This is the main file. Save it with any name you want in the MinGW working directory as usual. It begins with an include preprocessing directive to the file, ns.hh. Next you have the two using namespace statements. Then you have four initialization statements that use identifiers from the namespaces. Then you have the main function that uses an identifier from the namespace first. Now, try the last code above; it will include namespaces from the ns.hh file. It should work well. There is no output for the code.

using namespace std;
In order to use the cout for printing (displaying) that we saw in the previous parts of the series you need to include the iostream file. This is because the cout object is declared in the iostream file. This explains why we have been including the iostream file each time we need the cout object.

Now, cout belongs to a namespace called the std namespace. std means standard. The std namespace is related to the iostream file. So before you use the cout object in any program, you have to type the statement, "using namespace std;" higher up in the program file. Read and try the following code that works:

#include

int main()
{
using namespace std;
cout
return 0;
}

If you do not want to use the statement, "using namespace std;", then in order to use the cout object you would have to precede it with the namespace name, std and the scope operator. Read and try the following code that works:

#include

int main()
{

std::cout
return 0;
}

In order to use the predefined object, cout, you have to include the iostream file and you have to use the namespace that is called std. There are other predefined objects that you have to use like cout; I will not discuss those in this basic tutorial. Two approaches to use a namespace have been outlined above.

Block and the using Keyword
If the using statement is inside a block, then it will be applicable only inside that block. In the following code, the using statement is applicable only inside the block of the function, fn. So the cout statement in the block of the main function will not work. In fact the code will not compile.

#include

void fn()
{
using namespace std;
cout }

int main()
{
fn();
cout
return 0;
}

However, in the following code the cout object in the two different blocks will work since the "using namespace std;" is now at the top of the page just below the include directive. The using statement now has a file scope, so it is applicable everywhere in the file (and inside blocks). Read and try it.

#include
using namespace std;

void fn()
{
cout }

int main()
{
fn();
cout
return 0;
}

The \n character in each of the string causes the next string to be printed below the current string.

We have seen the basics of namespaces. There is more to namespaces than I have given you. However, I will not cover those extra bits in this basic series. Let us stop here and continue in the next part of the series.

Chrys

To arrive at any of the parts of this series, just type the corresponding title below in the Search Box of this page and click Search (you can also use any available links):

C++ Taking the Bull by the Horns - Part 1
C++ Taking the Bull by the Horns - Part 2
C++ Taking the Bull by the Horns - Part 3
C++ Taking the Bull by the Horns - Part 4
C++ Taking the Bull by the Horns - Part 5
C++ Taking the Bull by the Horns - Part 6
C++ Taking the Bull by the Horns - Part 7
C++ Taking the Bull by the Horns - Part 8
C++ Taking the Bull by the Horns - Part 9
C++ Taking the Bull by the Horns - Part 10
C++ Taking the Bull by the Horns - Part 11
C++ Taking the Bull by the Horns - Part 12
C++ Taking the Bull by the Horns - Part 13
C++ Taking the Bull by the Horns - Part 14
C++ Taking the Bull by the Horns - Part 15
C++ Taking the Bull by the Horns - Part 16
C++ Taking the Bull by the Horns - Part 17
C++ Taking the Bull by the Horns - Part 18
C++ Taking the Bull by the Horns - Part 19
C++ Taking the Bull by the Horns - Part 20
C++ Taking the Bull by the Horns - Part 21
C++ Taking the Bull by the Horns - Part 22
C++ Taking the Bull by the Horns - Part 23
C++ Taking the Bull by the Horns - Part 24
C++ Taking the Bull by the Horns - Part 25

Published by Chrys Forcha

I have more than 10 years experience in computer programming, software, electronics and telecommunications. I have a First Degree in Electronics and a Master's Degree in Technical Education. As well a...  View profile

To comment, please sign in to your Yahoo! account, or sign up for a new account.