عملگر تعیین دامنه (Scope Resolution Operator ::) در ++C
عملگر :: در ++C برای دسترسی به عناصر با دامنه تعریف شده (scope) استفاده میشود. این عملگر به کامپایلر میگوید که عنصر مورد نظر در کدام دامنه (کلاس، فضای نام، متغیر سراسری) قرار دارد.
کاربردهای اصلی:
۱. دسترسی به اعضای استاتیک کلاس
class MyClass { public: static int staticVar; // تعریف متغیر استاتیک static void staticFunc() { // تابع استاتیک cout << "Static function!" << endl; } }; // تعریف خارج از کلاس (نیاز به :: دارد) int MyClass::staticVar = 10; int main() { cout << MyClass::staticVar << endl; // 10 MyClass::staticFunc(); // "Static function!" }
۲. تعریف توابع عضو خارج از کلاس
class Rectangle { private: int width, height; public: Rectangle(int w, int h); int area(); // فقط اعلان }; // تعریف سازنده با :: Rectangle::Rectangle(int w, int h) : width(w), height(h) {} // تعریف تابع عضو با :: int Rectangle::area() { return width * height; } int main() { Rectangle rect(3, 4); cout << rect.area(); // 12 }
۳. دسترسی به متغیرهای سراسری (Global) با وجود متغیر محلی همنام
int x = 10; // متغیر سراسری int main() { int x = 20; // متغیر محلی cout << x; // 20 (محلی) cout << ::x; // 10 (سراسری با ::) }
۴. دسترسی به فضای نام (Namespaces)
namespace Physics { double gravity = 9.8; } int main() { cout << Physics::gravity; // 9.8 // یا با using: using namespace Physics; cout << gravity; // 9.8 }
تفاوت با عملگرهای . و ->:
-
.و->: برای دسترسی به اعضای شیء استفاده میشوند. -
::: برای دسترسی به اعضای کلاس/فضای نام بدون نیاز به نمونه شیء.
MyClass obj; cout << obj.staticVar; // صحیح (با .) cout << MyClass::staticVar; // صحیح (با ::)
نکات کلیدی:
-
برای توابع مجازی (virtual) در کلاسهای پایه و مشتق شده، از
::برای فراخوانی نسخه کلاس پایه استفاده میشود:class Base { public: virtual void show() { cout << "Base\n"; } }; class Derived : public Base { public: void show() override { Base::show(); // فراخوانی نسخه پایه cout << "Derived\n"; } };
-
در کلاسهای تو در تو (Nested Classes):
class Outer { public: class Inner { public: static void msg() { cout << "Nested!"; } }; }; int main() { Outer::Inner::msg(); // "Nested!" }
-
در قالبها (Templates):
template<typename T> class TemplateClass { public: static T data; }; template<typename T> T TemplateClass<T>::data = T(); // تعریف با ::
جمعبندی:
| کاربرد | مثال |
|---|---|
| اعضای استاتیک کلاس | MyClass::staticVar |
| تعریف توایع خارج کلاس | void MyClass::func() |
| حل تعارض نامها | ::globalVar |
| فضای نام | std::cout, Physics::gravity |
| کلاسهای پایه در وراثت | BaseClass::function() |
| کلاسهای تو در تو | Outer::Inner::method() |
در Geant4، عملگر تعیین دامنه (::) بهطور گسترده در ساختار کدها برای مدیریت کلاسها، توابع و متغیرها استفاده میشود. در اینجا چند نمونه کاربردی از کاربرد این عملگر در مثالهای Geant4 آورده شده است:
۱. تعریف توابع عضو خارج از کلاس
در کلاسهایی مانند DetectorConstruction، توابع عضو (مثل سازنده یا توابع مجازی) در فایلهای .cc با استفاده از :: تعریف میشوند:
// در فایل DetectorConstruction.cc B1DetectorConstruction::B1DetectorConstruction() { // سازنده: تعریف هندسه و مواد } void B1DetectorConstruction::ConstructSDandField() { // تعریف حسگرها و میدانها }
این رویکرد، خوانایی کد را افزایش میدهد و پیچیدگی هدر فایلها (.hh) را کاهش میدهد 15.
۲. دسترسی به اعضای استاتیک کلاس
برای متغیرها یا توابع استاتیک (مثل دادههای فیزیک)، از :: برای تعریف اولیه و دسترسی استفاده میشود:
// در فایل PhysicsList.cc void B1PhysicsList::ConstructParticle() { G4Geantino::GeantinoDefinition(); // فراخوانی عضو استاتیک کلاس }
این روش در PhysicsList برای مدیریت ذرات و فرآیندهای فیزیکی کاربرد دارد 12.
۳. استفاده در فضای نام (Namespace)
از نسخهی ۱۱ Geant4، کلاسهای مثالها در فضای نام B1، B2 و ... تعریف میشوند:
// در فایل exampleB1.cc using namespace B1; // فعالسازی فضای نام B1 auto* runManager = G4RunManagerFactory::Create(); // ایجاد RunManager
دسترسی به کلاسهایی مانند ActionInitialization فقط با B1::ActionInitialization امکانپذیر است 2.
۴. فراخوانی توابع کلاس پایه در وراثت
در کلاسهای مشتقشده (مثل PrimaryGeneratorAction)، برای فراخوانی توابع کلاس پایه از :: استفاده میشود:
void B1PrimaryGeneratorAction::GeneratePrimaries(G4Event* event) { G4VPrimaryGeneratorAction::GeneratePrimaries(event); // فراخوانی نسخه پایه // ... تولید ذرات }
این روش در SteppingAction برای جمعآوری دادههای انرژی نیز دیده میشود 213.
۵. مدیریت دادهها با ScoringManager
برای فعالسازی سیستم Score در خروجیگیری دادهها، کلاس G4ScoringManager با :: فراخوانی میشود:
// در فایل main.cc #include "G4ScoringManager.hh" G4ScoringManager* scManager = G4ScoringManager::GetScoringManager();
این دستور، شبکهبندی (mesh) و ذخیرهسازی پارامترهایی مانند EnergyDeposit را فعال میکند 13.
❗ نکات کلیدی:
-
تفاوت با
.و->:-
::برای عناصر کلاس/فضای نام (بدون نیاز به شیء:MyClass::staticVar). -
.و->برای اعضای شیء (مثلobj.method()) 15.
-
-
بهینهسازی کد: استفاده از
::در تعریف خارج از کلاس، زمان کامپایل را کاهش میدهد. -
خطاهای رایج: عدم استفاده از
::هنگام تعریف توابع عضو منجر به خطای لینکر میشود.
برای آزمایش این موارد، مثال B1 در مسیر basic/B1/ Geant4 بهعنوان نقطه شروع توصیه میشود