Broad Network


C++ Namespaces Basics

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

Forward: In this part of the series, we look at what is called Namespaces in C++.

By: Chrysanthus Date Published: 22 Aug 2012

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 defined. 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 <iostream>
        using namespace std;

These two lines especially the second one are related to the namespace concept. You will 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 defined (the code will not compile and will issue error messages – note the error messages 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 messages were issued. The reason the code did not compile is because you cannot have more than one identifier with the same name in the same scope. The scope in question here is 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. However, the 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.

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 Resolution Operator
The scope resolution operator is the operator, :: . It is used with namespaces. Read and try the following code (there is no output):

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()
    {
        first::fn();
        return 0;
    }

The above code is OK. It compiles successfully. There is no output because the cout object was not effective (preceded by //) 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, ident and the declaration of the function, fn. Inside the namespace, second, you have the initialization of the identifier, ident and the declaration of the function, fn. Note that inside the two namespaces, the object identifiers and the function declarations have the same names.

In the above code, in order to use the identifier from a namespace, you have to use the scope resolution operator. You begin with the name of the namespace, then the scope resolution operator, which is :: , then the identifier (or name of function which is still an 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 resolution operators in these two statements. In the namespaces, the two identifiers have the same name. Outside the namespaces, they are differentiated with the scope operator preceded by the namespace names.

Below the above two statements, you have the definition of the fn function from the namespace, first and the definition of the fn 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 namespaces, the two function names are the same. Outside the namespaces, they are differentiated with the scope operator preceded by the namespace names.

In the main function, the function, fn 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, identifiers of namespaces, 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 <iostream>” 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 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 (using) to namespace can lead to conflicts when you have the same identifier name in more than one namespace; that is a disadvantage of the second approach. It only prevents you from using the namespace name and the scope operator. If you have the same identifier name in more than one namespace, then to differentiate them outside the namespace, you have to use the namespace names and the scope operator. Now, read through the above code again.

Global Scope
In one file an identifier of file scope is an identifier that is not defined 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 <ns.hh>
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 <iostream>
using namespace std;

int main()
    {
        cout << "An exercise for the using statement.";

        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 <iostream>

int main()
    {

        std::cout << "We have not used the keyword, using.";

        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 use in C++ 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 <iostream>

void fn()
    {
        using namespace std;
        cout << "The above using statement is applicable only to this block.\n";
    }

int main()
    {
        fn();
        cout << "This is in a different block.\n";

        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 <iostream>
using namespace std;

void fn()
    {
        cout << "The above using statement is applicable to this block and the one below.\n";
    }

int main()
    {
        fn();
        cout << "This is in a different block.\n";

        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

Related Courses

C++ Course
Relational Database and Sybase
Windows User Interface
Computer Programmer – A Jack of all Trade – Poem
NEXT

Comments

Become the Writer's Fan
Send the Writer a Message