C++ Namespace

A namespace in C++ is a generalized scope. Its declaration begins with the reserved word, namespace, followed by a name of the programmer’s choice, and then the block in braces. The block contains basic declarations and/or definitions of C++ objects, functions, and other entities.

Consider the following two scalar statements in a global scope, in the following program:

#include
using namespace std;

int varId = 5;
float varId = 2.3;

int main()
{

    return 0;
}

An attempt to compile this program leads to a compilation error. There are two variables with the same name, varId. Though they are two different variables of two different types, int and float, the compiler rejects the two declarations because they are of the same name. The following program solves this problem by declaring the variables with the same name in two different generalized scopes:

#include
using namespace std;

namespace NA
    {
        int varId = 5;
    }

namespace NB
    {
        float varId = 2.3;
    }

int main()
{
    cout << NA::varId << '\n';
    cout << NB::varId << '\n';

    return 0;
}

The output is as follows:

5
2.3

There are two namespaces in the above program: NA, which has the definition of an integer, and NB, which has the definition of a float but with the same name as the integer for NA. Finally, when the program was run, the same name for two different variables was used. Note that to access the same name of two different variables, the particular name for the namespace must be used, followed by the common identifier. The namespace name and the common identifier are separated by the scope resolution operator, “::.” The name of the namespaces will differentiate the objects.

This article covers the basic concept of a namespace and its usage in the C++ programming language. To follow this article, you should have a basic knowledge of the C++ language. You should also have knowledge of the C++ scope, though it is briefly explained in this article. To learn more about C++ scope, search for the phrase, “Scope in C++” (without quotes) in the search box of any linuxhint.com web page and press Enter. This will lead you to the article this author wrote.

Article Content

  • Introduction – see above
  • What is a Namespace?
  • The using Directive
  • Nested Namespaces
  • Standard Namespace
  • Conclusion

What is a Namespace?

A declarative region is the largest part of a program in which the name of an entity (variable) is valid. This region is called a scope. A namespace in C++ is a generalized scope whose main purpose is to solve name conflicts. A namespace has basic declarations and/or definitions of entities.

Global Namespace and Its Problem

The global namespace is the global scope. Consider the following short program:

#include
using namespace std;

int ident = 55;
float ident = 12.17;

int main()
{

    return 0;
}

In the above program, there are two variables, both called ident. These variables are in the global scope; that is, they are in the global namespace. An attempt to compile this program will fail with an error message. The global scope does not accept more than one variable with the same name, so there is a need for a custom namespace.

Custom Namespace

A namespace does not have only one name. Instead, a namespace has a set of names to avoid conflict with other sets of names. To avoid conflict lower in the code, precede each name with the name of the namespace and :: . The following program illustrates this using two custom namespaces:

#include
using namespace std;

namespace NA
    {
        int varInt = 6;
        float flt;
    }

namespace NB
    {
        int varInt = 7;
        float flt;
    }

int main()
{
    cout << NA::varInt << '\n';
    cout << NB::varInt << '\n';
    NA::flt = 2.5;
    NB::flt = 4.8;
    cout << NA::flt << '\n';
    cout << NB::flt << '\n';

    return 0;
}

The output is:

6
7
2.5
4.8

Note that the names NA::flt and NB::flt have ultimately been defined in the main() function. C++ does not allow such a definition in the global scope.

Note that the custom namespace is a nested namespace for the global namespace.

The using Directive

To avoid typing “namepace::name” all the time instead of just “name” after declaring the namespace, you may use the using directive. The syntax to use the using directive is as follows:

using namespace Namespace_name;

The using directive is not a preprocessor directive, so it ends with a semicolon (;).

The following program illustrates the use of the using directive and more:

#include
using namespace std;

namespace NB
    {
        int varInt = 7;
        int func ()
            {
                return varInt;
            }
    }

int fn()
    {
        using namespace NB;
        int myVar2 =  func();
        //other objects and functions from NB follow.
        return myVar2;
    }

int myVar3 = NB::func();

int main()
{
    cout << fn() << ' ' << myVar3 << '\n';

    return 0;
}

The output of this program is 7 7. The term “using namespace NB;” has been placed at the beginning of the fn() definition. The func() from the NB namespace is called just below that, without preceding with “NB::.”

A variable declared in the global scope (global namespace) is seen from the point of declaration to the end of the file. It is also seen in the nested namespaces (nested scopes), such as the nested fn() function scope above. The using directive joins its namespace from the position at which it is placed to the end of the scope in which it is placed.

The name func() from the NB namespace cannot be seen below the fn() definition because “using namespace NB;” was placed within the function scope (block). Under this condition, to use “func()” outside the NB namespace block (scope), it must be preceded by “NB::,” as in the following statement:

int myVar3 = NB::func();

The using directive joins its namespace with the outer nesting namespace from the position at which it is placed to the end of the outer nesting namespace. In the following program, the NA namespace is joined with the global namespace. Both namespaces then extend into the fn() function definition namespace, in which they are joined with the NB namespace. The NB namespace ends at the end of the fn() function definition, and the two previous namespaces carry on until the end of the file (read through the code).

#include
using namespace std;

namespace NA
    {
        int varInt = 6;
        int func ()
            {
                return varInt;
            }
       
    }

namespace NB
    {
        int varInt = 7;
        int func ()
            {
                return varInt;
            }
    }

using namespace NA;
int myVar0 = varInt;
//other objects and functions from :: and NB follow.

int fn()
    {
        int myVar1 = varInt;
        using namespace NB;
        int myVar2 =  NB::func();
        //other objects and functions from NB follow, till end of this scope.
        return myVar1 + myVar2;
    }

//Only objects and functions from :: and NB follow.

int myVar3 = NB::func();

int main()
{
    cout << myVar0 << ' ' << fn() << ' ' << myVar3 << '\n';

    return 0;
}

The output is 6, 13, 7.

Note: The global namespace is indicated with :: , meaning that there is nothing before the scope resolution operator that follows.

Below the statement, the “using namespace NA;” variables from the global and NA namespaces can be used without an indication of their source namespace. The next statement uses the varInt of the NA namespace. The global and NA combined namespace region extends into the fn() function namespace. So, the varInt of the first statement in the fn() function scope, is of the NA namespace.

Since the region for the global and NA namespaces extend throughout the fn() scope, after the “int myVar2 = NB::func();,” any name from the NB namespace can only be used in the fn() scope without preceding it with “NB::,” only if it did not occur in the NA and global namespaces (blocks). Otherwise, it should be preceded by “NB::.” The region of the combined namespaces for NA and global continue below the fn() definition and into the main() function until the end of the file.

The extension of the NB namespace begins from “int myVar2 = NB::func();” in the fn() block and ends at the end of the fn() definition block.

Note: Namespaces whose regions are joined should not have the same variable name in their different namespace blocks, as this would still cause conflict.

Namespace Regions

A namespace is a scope. Apart from the global namespace (global scope), any namespace should be declared in a block. That block is the first part of the possibly distributed regions of the namespace. With the using directive, the namespace can be extended as regions in other scopes.

Entities declared in a namespace body are said to be members of the namespace, and names introduced by these declarations into the declarative region of the namespace are said to be member names of the namespace.

Nested Namespaces

The following program shows nested namespaces:

#include
using namespace std;

namespace A
    {
        int i = 1;
        namespace B
            {
                int i = 2;
                namespace C
                    {
                        int i = 3;
                    }
            }
    }

int main()
{
    cout << A::i << ' ' << A::B::i << ' ' <<  A::B::C::i << '\n';

    return 0;
}

The output is:

1 2 3

Notice that the three values have been accessed using the scope resolution operator.

Standard Namespace

C++ has a library called the standard library. The names of objects, functions, and other entities in this library are from a namespace called the standard namespace, written as std. The standard library contains sub-libraries, and one of these sub-libraries is iostream. The iostream library contains the object cout, which is used to send results to the console (terminal).

The name cout must be in the std namespace. To use iostream with its std namespace, the program should be as follows:

#include <iostream>
using namespace std;

Note the use of the using directive and std. The term “#include <iostream>” is a preprocessor directive and does not end with a semicolon. It includes the iostream “file” at the position of its directive.

Conclusion

A namespace is a scope. The namespace description (definition) contains basic declarations and/or definitions of C++ objects, functions, and other entities. Outside the namespace definition, the name can be accessed with the syntax, “namespaceName::name.” Apart from the global namespace (global scope), any namespace should be declared in a block. That block is the first part of the possibly distributed regions of the namespace. With the using directive, the namespace can be extended as regions in other scopes. Namespaces whose regions are joined should not have the same variable name in their different namespace blocks, as this would still cause name conflict.

Chrys



from Linux Hint https://ift.tt/3nT86dF

Post a Comment

0 Comments