Namespace (فضای نام) در ++C چیست؟

?What is Namespace in C Plus Plus

what-is-namespace-in-c-plus-plus

سلام به کاربران روکسو. در این قسمت و قسمت‌های آینده به معرفی فضای نام یا Namespace در زبان برنامه‌نویسی ++C خواهیم پرداخت.

ابتدا قطعه‌کُد زیر را در نظر بگیرید:

// A program to demonstrate need of namespace
int main()
{
    int value;
    value = 0;
    double value; // Error here
    value = 0.0;
}

خروجی آن به این صورت است:

Compiler Error:
'value' has a previous declaration as 'int value'

در هر محدوده‌ای، می‌توان تنها یک نام را تعریف کرد. بنابراین 2 متغیر با نامی یکسان در یک محدوده، نمی‌توانند تعریف شوند. با استفاده از فضای نام‌ها (namespaces)، می‌توان 2 متغیر یا تابع عضو، نامی یکسان داشته باشند.

// Here we can see that more than one variables 
// are being used without reporting any error.
// That is because they are declared in the 
// different namespaces and scopes.
#include <iostream>
using namespace std;
  
// Variable created inside namespace
namespace first
{
    int val = 500;
}
  
// Global variable
int val = 100;
  
int main()
{
    // Local variable
    int val = 200;
  
    // These variables can be accessed from
    // outside the namespace using the scope
    // operator ::
    cout << first::val << '\n'; 
  
    return 0;
}

خروجی قطعه‌کُد بالا به این صورت است:

500

تعریف و ایجاد (Definition and Creation)

فضای نام‌ها اجازه‌ی گروه‌بندی نام‌هایی که محدوده‌ی سراسری دارند را در محدوده‌های کوچک‌تر،‌ می‌دهند. آن‌ها در محدوده‌ی فضای نام فراهم می‌شوند. این امکان سازماندهی عناصر برنامه را در داخل محدوده‌های مختلف که توسط نام‌ها شناخته می‌شود را می‌دهد.

  • فضای نام یک ویژگی اضافه‌شده در ++C است و در زبان C ارائه نشده است.
  • یک فضای‌نام یک ناحیه‌ی اعلام شده است که یک محدوده برای شناسه‌ها (نام‌‌های انواع، تابع، متغیر و غیره) در داخل آن، فراهم کرده است.
  • فضای نام‌های مختلف با نامی یکسان، مجاز هستند. همه‌ی اعلامیه در آن‌ها در محدوده‌ی نام‌گذاری شده اعلام شده هستند.

یک فضای‌نام، با کلمه‌ی کلیدی namespace به همراه نام آن تعریف می‌شود. به این صورت:

namespace namespace_name 
{
   int x, y; // code declarations where 
             // x and y are declared in 
             // namespace_name's scope
}
  • فضای‌نام اعلام‌شده تنها در محدوده‌ی سراسری نمایش داده می‌شود.
  • فضای نام اعلام‌شده می‌تواند در داخل فضای نام دیگر، تودرتو باشد.
  • فضای نام اعلام‌شده مشخص‌کننده‌ی دسترسی (public یا private) ندارد.
  • نباید بعد از تعریف فضای نام، سِمی‌کالن بگذارید.
  • می‌توانیم تعریف فضای‌نام را به واحد‌های مختلف تقسیم کنیم.
// 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;
}

خروجی قطعه‌کُد بالا به این صورت است:

5
200
100

کلاس‌ها و فضای‌نام (Classes and Namespace)

در قطعه‌کُد زیر، به طور ساده، کلاس‌ها در یک فضای‌نام ایجاده شده است:

// A C++ program to demonstrate use of class
// in a namespace
#include <iostream>
using namespace std;
  
namespace ns
{
    // A Class in a namespace
    class geek
    {
    public:
        void display()
        {
            cout << "ns::geek::display()\n";
        }
    };
}
  
int main()
{
    // Creating Object of geek Class
    ns::geek obj;
  
    obj.display();
  
    return 0;
}

خروجی آن به این صورت است:

ns::geek::display()

کلاس‌ها همچنین می‌توانند داخل فضای‌نام اعلام شده و در خارج از فضای نام تعریف شوند، با استفاده از نحوهِ (‌syntax) زیر:

// A C++ program to demonstrate use of class
// in a namespace
#include <iostream>
using namespace std;
  
namespace ns
{
    // Only declaring class here
    class geek;
}
  
// Defining class outside
class ns::geek
{
public:
    void display()
    {
        cout << "ns::geek::display()\n";
    }
};
  
int main()
{
    //Creating Object of geek Class
    ns::geek obj;
    obj.display();
    return 0;
}

خروجی آن به این صورت است:

ns::geek::display()

این امکان برای متُد‌ها هم فراهم است که خارج از فضای‌نام تعریف شوند:

// A C++ code to demonstrate that we can define 
// methods outside namespace.
#include <iostream>
using namespace std;
  
// Creating a namespace
namespace ns
{
    void display();
    class geek
    {
    public:
       void display();
    };
}
  
// Defining methods of namespace
void ns::geek::display()
{
    cout << "ns::geek::display()\n";
}
void ns::display()
{
    cout << "ns::display()\n";
}
  
// Driver code
int main()
{
    ns::geek obj;
    ns::display();
    obj.display();
    return 0;
}

خروجی آن به این صورت است:

ns::display()
ns::geek::display()

می‌توان بیش‌از یک فضای‌نام در فضای سراسری ایجاد کرد. به 2 صورت می‌توان این کار را انجام داد.

فضای‌نام‌ها نام‌های مختلفی داشته باشند

// A C++ program to show more than one namespaces 
// with different names.
#include <iostream>
using namespace std;
  
// first name space
namespace first
{
   int func() {  return 5; }
}
  
// second name space
namespace second
{
   int func() { return 10; }
}
  
int main()
{
   // member function of namespace
   // accessed using scope resolution operator
   cout << first::func() <<"\n";        
   cout << second::func() <<"\n"; 
   return 0;
}

خروجی قطعه‌کُد بالا به این صورت است:

5
10

گسترش فضای‌نام‌ها (بااستفاده‌ی دوباره از همان نام)

این امکان‌پذیر است که 2 فضای نام ایجاد کنید که نام یکسانی داشته باشند. دومین فضای‌نام چیزی جز ادامه‌ی فضای‌نام اول نیست. به طور ساده‌تر، می‌توان گفت که هر دو فضای‌نام متفاوت نیستند، اما در بخش‌های تعریف‌شده یکسان هستند.

// C++ program to demonstrate namespace exntension
#include <iostream>
using namespace std;
  
// first name space
namespace first 
{ 
   int val1 = 500;  
}
  
// rest part of the first namespace
namespace  first 
{ 
   int val2 = 501;  
}
  
int main()
{
   cout << first::val1 <<"\n";        
   cout << first::val2 <<"\n"; 
   return 0;
}

خروجی قطعه‌کُد بالا به این صورت است:

500
501

فضای‌نام‌های نامگذاری‌نشده یا بی‌نام (Unnamed Namespaces)

  • آن‌ها به طور مستقیم در همان برنامه قابل استفاده هستند و برای اعلام شناسه‌های منحصربه‌فرد استفاده شده‌اند.
  • در فضای‌نام‌های نام‌گذاری‌نشده (بی‌نام)، نام فضای‌نام در اعلام فضای‌نام در نظر گرفته نمی‌شود.
  • نام فضای نام، به طور منحصربه‌فرد توسط کامپایلر ایجاد می‌شود.
  • فضای‌نام‌های نا‌م‌گذاری‌نشده که ایجاد می‌کنید، تنها در فایلی که فضای‌نام در آن تعریف شده، قابل دسترس است.
  • فضای‌نام‌های نام‌گذاری نشده برای متغیر‌های اعلام‌شده‌ی استاتیک (static declaration of variables) جایگزین هستند.
// C++ program to demonstrate working of unnamed 
// namespaces
#include <iostream>
using namespace std;
  
// unnamed namespace declaration
namespace 
{
   int rel = 300; 
}
  
int main()
{
   cout << rel << "\n"; // prints 300
   return 0;
}

خروجی قطعه‌کُد بالا به این صورت است:

300

روش‌های مختلف برای دسترسی به فضای نام

در ++C،‌ به 2 صورت می‌توان به متغیر‌ها و توابع فضای‌نام دسترسی داشت.

  1. روش معمول

// C++ program to demonstrate accessing of variables
// in normal way, i.e., using "::"
#include <iostream>
using namespace std;
  
namespace geek
{
    int rel = 300; 
}
  
int main()
{
    // variable ‘rel’ accessed 
    // using scope resolution operator
    cout << geek::rel << "\n";  // prints 300
  
    return 0;
}

خروجی قطعه‌کُد بالا به این صورت است:

300

2. با استفاده از دستور 'using'

// C++ program to demonstrate accessing of variables
// in normal way, i.e., using "using" directive
#include <iostream>
using namespace std;
  
namespace geek
{
    int rel = 300; 
}
  
// use of ‘using’ directive
using namespace geek;
  
int main()
{
   // variable ‘rel’ accessed 
   // without using scope resolution variable
   cout << rel << "\n";        //prints 300
    
   return 0;
}

خروجی قطعه‌کُد بالا به این صورت است:

300

استفاده از فضای‌نام در هِدر‌فایل‌ها (header files)

می‌توان فضای‌نام را در یک فایل ایجاد کرد و در دیگر قسمت‌های برنامه‌ به آن دسترسی داشت. این کار به این صورت انجام می‌شود.

  • باید 2 فایل را ایجاد کرد. یکی از این 2 فایل باید شامل فضای نام و همه‌ی اعضای داده و توابع که می‌خواهیم بعدا استفاده کنیم، باشد.
  • در دیگر قسمت‌های برنامه می‌‌توان به صورت مستقیم فایل اول که شامل فضای نام است را برای استفاده از همه‌ی اعضای داده و توابعِ در آن استفاه کرد.

فایل 1

// file1.h 
namespace foo
{
    int value() 
    { 
       return 5;    
    }
}

فایل 2

// file2.cpp - Not to be executed online
#include <iostream>
#include “file1.h” // Including file1
using namespace std;
  
int main () 
{
    cout << foo::value();
    return 0;
}

همان‌طور که مشاهده کردید، فضای‌نام در file1.h ایجاده شده است و تابع ()value آن فضای‌نام در file2.cpp استفاده شده است.

فضای‌نام‌های تودرتو (Nested Namespaces)

در ++C، فضای‌نام‌ها می‌توانند تودرتو باشند، به عنوان مثال، یک فضای‌‌نام در داخل فضای‌نام دیگری. در این حالت، دسترسی به فضای‌‌نام‌ها به صورت سلسه‌مراتب رُخ خواهد داد.

// C++ program to demonstrate nesting of namespaces
#include <iostream>
using namespace std;
  
// Nested namespace
namespace out
{
  int val = 5; 
  namespace in
  {
      int val2 = val;    
  }
}
  
// Driver code
int main()
{
  cout << out::in::val2;   // prints 5
  return 0;
}

خروجی قطعه‌کُد بالا به این صورت است:

5

نام مستعار برای فضای‌نام (Namespace Aliasing)

می‌توانید یک نام مستعار را برای نام فضای‌نامتان برای استفاده‌ی راحت استفاده کنید. فضای‌نام‌های موجود می‌توانند با نام‌های مستعار جدید، نام‌گذاری شوند که نحوِ (syntax) به این صورت است:

namespace new_name = current_name;
#include <iostream>
  
namespace name1 
{
    namespace name2 
    {
         namespace name3 
         {
             int var = 42;
         }
    }
}
  
// Aliasing 
namespace alias = name1::name2::name3;
   
int main()
{
    std::cout << alias::var << '\n';
}

خروجی قطعه‌کُد بالا به این صورت است:

42

منبع: وب سایت geeksforgeeks

نویسنده شوید
دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.