سلام به کاربران روکسو. در این قسمت و قسمتهای آینده به معرفی فضای نام یا 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 صورت میتوان به متغیرها و توابع فضاینام دسترسی داشت.
-
روش معمول
// 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