فضای نام یا Namespace در ++C

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

مشابه همین وضعیت در برنامه‌های ++C هم ممکن است به وجود بیاید. برای مثال، ممکن است در کدتان تابعی به نام ()xyz تعریف کنید و در یک کتابخانه دیگر نیز دقیقاً تابعی با همان نام ()xyz موجود باشد. در این حالت کامپایلر هیچ اطلاعی ندارد که باید به کدام نسخه از تابع ()xyz اشاره کند.

برای حل این مشکل یک فضای نام تعریف می‌کنیم و از آن به عنوان همان اطلاعات اضافی برای متمایزکردن توابع، کلاس‌ها، متغیرها و … استفاده می‌کنیم. با استفاده از فضای نام، می‌توان زمینه‌ای (context) که نام‌ها در آن تعریف می‌شوند را تعیین کرد. در واقع، یک فضای نام یک محدوده (scope) را تعریف می‌کند.

تعریف فضای نام

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

namespace namespace_name {
   // code declarations
}

برای فراخوانی نسخه‌ی تابع یا متغیر در یک فضای نام مشخص، نام آن فضا به همراه (::) و سپس نام تابع یا متغیر را قرار می‌دهیم.

name::code;  // code could be variable or function.

در مثال زیر مشاهده می‌کنیم که چگونه فضای نام، دامنه متغیر یا توابع را محدود می‌کند.

#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;
   }
}

int main () {
   // Calls function from first name space.
   first_space::func();
   
   // Calls function from second name space.
   second_space::func(); 

   return ;
}

اگر کد فوق را کامپایل و سپس اجرا کنیم، نتیجه زیر به دست می‌آید.

Inside first_space
Inside second_space

دستور using

با استفاده از دستور using namespace می‌توان از نوشتن فضای نام قبل از هربار نوشتن نام متغیر یا تابع اجتناب کرد. این دستور به کامپایلر اعلام می‌کند که کدهای متعاقب، از نام‌های موجود در فضای نام تعیین شده بهره خواهند برد. بنابراین فضای نام به کد زیر اعمال می‌شود.

#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;
int main () {
   // This calls function from first name space.
   func();
   
   return ;
}

اگر کد بالا اجرا شود، خروجی زیر پدید می‌آید.

Inside first_space

دستور using را همچنین می‌توان برای ارجاع به یک آیتم خاص درون فضای نام نیز به کار گرفت. برای مثال، اگر تنها قسمتی از فضای نام std که شما می‌خواهید استفاده کنید cout باشد، می‌توانید به روش زیر به آن ارجاع دهید.

using std::cout;

کدهای متعاقب بدون نوشتن نام فضا می‌توانند به cout دسترسی داشته باشند، اما برای دسترسی به دیگر آیتم‌ها از فضای نام std کماکان نام فضا باید صریحاً بیان گردد.

#include <iostream>
using std::cout;

int main () {
   cout << "std::endl is used with std!" << std::endl;
   
   return ;
}

اگر کد فوق را اجرا کنید، خروجی زیر تولید می‌شود.

std::endl is used with std!

نام‌های تعریف شده در دستور using از همان قواعد دامنه‌های معمولی تبعیت می‌کنند. نام‌ها از محل نوشتن دستور using تا انتهای دامنه‌ای که دستور در آن تعریف شده است قابل رویت هستند. عناصری با نام مشابه که در دامنه‌های دیگر تعریف شده اند مخفی خواهند ماند.

مطلب پیشنهادی:  انواع داده در ++C

فضای نام‌های ناپیوسته

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

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

namespace namespace_name {
   // code declarations
}

فضاهای نام تودرتو

می‌توان فضاهای نام را به صورت تودرتو تعریف کرد، یعنی یک فضای نام را درون فضای نام دیگری قرار داد.

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

با استفاده از عملگر وضوح (resolution) می‌توان به اعضای یک فضای نام داخلی به شکل زیر دسترسی یافت.

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

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

در عبارات فوق، اگر از فضای نام «namespace_name1» استفاده کنید، آنگاه می‌توانید به عناصر موجود در فضای نام «namespace_name2» به صورت زیر دسترسی داشته باشید.

#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 ;
}

با اجرای این کد خروجی زیر حاصل می‌گردد.

Inside second_space

منبع: ترجمه از سایت tutorialspoint.com

مطالعه دیگر جلسات این آموزش<< جلسه قبلی                    جلسه بعدی >>

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *