Namespaces in C++ | What does Namespaces in C++ Mean?

Namespaces in C++

Think about a circumstance when we have two people with a similar name, Zara, in a similar class. At whatever point we need to separate them, we would need to utilize some extra data alongside their name, as either the territory, if they live in various regions or their mom’s or father’s name, and so forth. 

The same circumstance can emerge in your C++ applications. For instance, you may be thinking of some code that has a capacity called xyz(), and there is another library accessible which is likewise having the same capacity xyz(). Presently the compiler has no chance to know which variant of xyz() work you are alluding to inside your code. 

A namespace is intended to beat this trouble. It is utilized as extra data to separate comparative capacities, classes, factors, and a similar name accessible in various libraries. Using namespace, you can characterize the setting where names are characterized. A namespace characterizes a degree.

Definition:

Namespaces permit us to bunch named elements that in any case would have a worldwide degree into smaller extensions, giving them namespace scope. This permits putting together the components of projects into various consistent extensions alluded to by names.

  • Namespace is a component included C++ and not present in C. 
  • A namespace is a revelatory district that gives a degree to the identifiers (names of the kinds, work, factors and so forth) inside it. 
  • Various namespace blocks with a similar name are permitted. All presentations inside those squares are proclaimed in the named scope.
  • Namespaces in C++ are utilized to coordinate such a large number of classes with the goal that it tends to be not difficult to deal with the application. 
  • For getting to the class of a namespace, we need to utilize namespacename::classname. We can utilize catchphrases with the goal that we don’t need to utilize total names constantly. 
  • In C++, worldwide namespace is the root namespace. The global::std will consistently allude to the namespace “sexually transmitted disease” of C++ Framework.

A namespace definition starts with the catchphrase namespace followed by the namespace name as follows:

namespace namespace_name 
{
   int x, y; // code declarations where 
             // x and y are declared in 
             // namespace_name's scope
}

Using directives:

The using directive permits every one of the names in a namespace to be used without the namespace-name as an explicit qualifier. Utilize a using directive in an execution document (for example *.cpp) on the off chance that you are utilizing a few unique identifiers in a namespace; assuming you are simply utilizing a couple of identifiers, consider a using-declaration to just bring those identifiers into the scope and not every one of the identifiers in the namespace. On the off chance that a nearby factor has a similar name as a namespace variable, the namespace variable is covered up. It is an error to have a namespace variable with a similar name as a global variable.

The Global Namespace:

On the off chance that an identifier isn’t pronounced in an unequivocal namespace, it is important for the implied worldwide namespace. By and large, attempt not to make revelations at a worldwide degree whenever the situation allows, aside from the section point primary Function, which is needed in the worldwide namespace. To expressly qualify a worldwide identifier, utilize the degree goal administrator with no name, as in::SomeFunction(x);. This will separate the identifier from anything with a similar name in some other namespace, and it will likewise assist with making your code simpler for others to comprehend.

Declaring namespaces and namespace members:

Ordinarily, you pronounce a namespace in a header record. On the off chance that your capacity executions are in a different record, qualify the capacity names, as in this model.

//contosoData.h
#pragma once
namespace ContosoDataServer
{
    void Foo();
    int Bar();
}

Function implementations in contosodata.cpp should use the fully qualified name, even if you place a using directive at the top of the file:

#include "contosodata.h"
using namespace ContosoDataServer;

void ContosoDataServer::Foo() // use fully-qualified name here
{
   // no qualification needed for Bar()
   Bar();
}

int ContosoDataServer::Bar(){return 0;}


A namespace can be announced in different squares in a solitary document and various records. The compiler consolidates the parts during preprocessing, and the subsequent namespace contains every one of the individuals pronounced the parts altogether. An illustration of this is the sexually transmitted disease namespace announced in every one of the header records in the standard library. 

Individuals from a named namespace can be characterized outside the namespace in which they are proclaimed by the express capability of the name being characterized. Nonetheless, the definition should show up after the mark of presentation in a namespace that encases the affirmation’s namespace. For instance:

// defining_namespace_members.cpp
// C2039 expected
namespace V {
    void f();
}

void V::f() { }        // ok
void V::g() { }        // C2039, g() is not yet a member of V

namespace V {
    void g();
}

This error can occur when the namespace members are declared across multiple header files, and you have not included those headers in the correct order.

The std Namespace:

All C++ standard library types and functions are declared in the std namespace or namespaces nested inside std.

Creation:

  • Namespace declarations show up just at worldwide degrees. 
  • Namespace declaration can be settled inside another namespace. 
  • Namespace declarations don’t approach specifiers. (Public or private) 
  • No compelling reason to give semicolon after the end support of the meaning of namespace. 
  • We can part the meaning of a namespace with more than a few units.
// Creating namespaces
#include <iostream>
using namespace std;
namespace ns1
{
    int value()    { return 5; }
}
namespace ns2 
{
    const double x = 100;
    double value() {  return 2*x; }
}
  
int main()
{
    // Access value function within ns1
    cout << ns1::value() << 'n'; 
  
    // Access value function within ns2
cout << ns2::value() << 'n'; 
  
    // Access variable x directly
    cout << ns2::x << 'n';       
  
    return 0;
}


Output:

5

200

100

Nested Namespaces:

Namespaces can be settled where you can characterize one namespace inside another name space as follows –

namespace namespace_name1 {
   // code declarations
   namespace namespace_name2 {
      // code declarations
   }
}


You can get to individuals from settled namespace by the use of resolution operators as follows –

// to access members of namespace_name2
using namespace namespace_name1::namespace_name2;

// to access members of namespace:name1
using namespace namespace_name1;


In the above articulations assuming you are using namespace_name1, it will make components of namespace_name2 accessible in the scope as follows –

#include <iostream>
using namespace std;

// first name space
namespace first_space {
   void func() {
      cout << "Inside first_space" << endl;
   }
   
   // second name space
   namespace second_space {
      void func() {
         cout << "Inside second_space" << endl;
      }
   }
}

using namespace first_space::second_space;
int main () {
   // This calls function from second name space.
   func();
   
   return 0;
}

If we compile and run above code, this would produce the following result –

Inside second_space

Inline Namespaces:

Rather than a common settled namespace, individuals from an inline namespace are treated as individuals from the parent namespace. This trademark empowers subordinate contention queries on over-burden capacities to chip away at capacities with over-burdens in a parent and a settled inline namespace. It additionally empowers you to proclaim a specialization in a parent namespace for a layout that is pronounced in the inline namespace. The accompanying model shows how outer code ties to the inline namespace naturally:

//Header.h
#include <string>

namespace Test
{
    namespace old_ns
    {
        std::string Func() { return std::string("Hello from old"); }
    }

    inline namespace new_ns
    {
        std::string Func() { return std::string("Hello from new"); }
    }
}

#include "header.h"
#include <string>
#include <iostream>

int main()
{
    using namespace Test;
    using namespace std;

    string s = Func();
    std::cout << s << std::endl; // "Hello from new"
    return 0;
}

The following example shows how you can declare a specialization in a parent of a template that is declared in an inline namespace:

namespace Parent
{
    inline namespace new_ns
    {
         template <typename T>
         struct C
         {
             T member;
         };
    }
     template<>
     class C<int> {};
}

Namespace aliases:

You can utilize inline namespaces as a forming component to oversee changes to the public interface. For instance, you can make a solitary parent namespace and epitomize every form of the interface in its namespace settled inside the parent. The namespace that holds the latest or favoured adaptation is qualified as inline and is accordingly uncovered as an immediate individual from the parent namespace. Customer code that conjures the Parent::Class will consequently tie to the new code. Customers that like to utilize the more seasoned variant can, in any case, get to it by utilizing the completely qualified way to the settled namespace that has that code. 

The accompanying model shows two variants of an interface, each in a settled namespace. The v_20 namespace has some adjustment from the v_10 interface and is set apart as inline. Customer code that utilizes the new library and calls Contoso::Funcs::Add will summon the v_20 variant. Code that endeavors to call Contoso::Funcs::Divide will currently get an assemble time blunder. On the off chance that they truly need that work, they can in any case get to the v_10 form by unequivocally calling Contoso::v_10::Funcs::Divide.

namespace Contoso
{
    namespace v_10
    {
        template <typename T>
        class Funcs
        {
        public:
            Funcs(void);
            T Add(T a, T b);
            T Subtract(T a, T b);
            T Multiply(T a, T b);
            T Divide(T a, T b);
        };
    }

    inline namespace v_20
    {
        template <typename T>
        class Funcs
        {
        public:
            Funcs(void);
            T Add(T a, T b);
            T Subtract(T a, T b);
            T Multiply(T a, T b);
            std::vector<double> Log(double);
            T Accumulate(std::vector<T> nums);
      };
    }
}

Anonymous or unnamed namespaces:

You can create an explicit namespace but not give it a name:

namespace
{
    int MyFunc(){}
}

This is called an anonymous or unknown namespace. It is valuable to make variable affirmations imperceptible to code in different records (for example, give them inside linkage) without making a named namespace. All code in a similar record can see the identifiers in an anonymous namespace. Yet, the identifiers, alongside the namespace itself, are not noticeable outside that document—or all the more unequivocally outside the interpretation unit.

Scope resolution operator (::):

We can explicitly specify any name declared in a namespace using the namespace’s name and the scope resolution “::” operator with the identifier.

namespace New_space
{
    class X
    {
        static int i;
        public:
        void func();
    };
     
    // class name declaration
    class Y;    
     
}
 
// Initializing static class variable
int New_space::X::i=23;      
 
class New_space::Y
{
    int a;
    public:
    int getdata()
    {
        cout << a;
    }
    // Constructor declaration
    Y();   
}
 
// Constructor definition explicitly
New_space::Y::Y()   
{
    a=0;
}

Discontiguous Namespace in C++:

As we probably know, a namespace in C++ can be characterized in a few sections; hence it consists of the amount of its independently characterized parts. Thus, if one piece of the namespace requires a name characterized in another document, that name should, in any case, be announced in its extension. Composing the accompanying namespace in an accompanying way either characterizes another namespace or adds new components to a current one:

Advantages:

The standard library contains the basic usefulness you use in building your applications like holders, calculations, and so on. On the off chance that names utilized by these were out in the open, for instance, if they characterized a line class around the world, you’d always be unable to utilize a similar name again without clashes. So they made a namespace, sexually transmitted disease to contain this change.

Disadvantages:

Calls to functions can be ambiguous if they are defined in more than one place.
To disambiguate, we use the prefix NameOfNamespace:: before the function. This is less risky when using multiple libraries.

This brings us to the end of the blog on Namespaces in C++. We hope that you were able to gain comprehensive knowledge about Namespaces in C++. If you wish to learn more such concepts in programming, do check out Great Learning Academy’s Free Online Courses and upskill today.

0


Source link

WORLD NEWS