عملگر تعیین دامنه (Scope Resolution Operator ::) در ++C

  • صفحه اول
  • عملگر تعیین دامنه (Scope Resolution Operator ::) در ++C
image

عملگر تعیین دامنه (Scope Resolution Operator ::) در ++C

عملگر :: در ++C برای دسترسی به عناصر با دامنه تعریف شده (scope) استفاده می‌شود. این عملگر به کامپایلر می‌گوید که عنصر مورد نظر در کدام دامنه (کلاس، فضای نام، متغیر سراسری) قرار دارد.


کاربردهای اصلی:

۱. دسترسی به اعضای استاتیک کلاس

cpp
 
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!"
}

۲. تعریف توابع عضو خارج از کلاس

cpp
 
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) با وجود متغیر محلی هم‌نام

cpp
 
int x = 10; // متغیر سراسری

int main() {
    int x = 20; // متغیر محلی

    cout << x;       // 20 (محلی)
    cout << ::x;     // 10 (سراسری با ::)
}

۴. دسترسی به فضای نام (Namespaces)

cpp
 
namespace Physics {
    double gravity = 9.8;
}

int main() {
    cout << Physics::gravity; // 9.8
    
    // یا با using:
    using namespace Physics;
    cout << gravity; // 9.8
}

تفاوت با عملگرهای . و ->:

  • . و ->: برای دسترسی به اعضای شیء استفاده می‌شوند.

  • ::: برای دسترسی به اعضای کلاس/فضای نام بدون نیاز به نمونه شیء.

cpp
 
MyClass obj;
cout << obj.staticVar;    // صحیح (با .)
cout << MyClass::staticVar; // صحیح (با ::)

نکات کلیدی:

  1. برای توابع مجازی (virtual) در کلاس‌های پایه و مشتق شده، از :: برای فراخوانی نسخه کلاس پایه استفاده می‌شود:

    cpp
     
    class Base {
    public:
        virtual void show() { cout << "Base\n"; }
    };
    
    class Derived : public Base {
    public:
        void show() override {
            Base::show(); // فراخوانی نسخه پایه
            cout << "Derived\n";
        }
    };
  2. در کلاس‌های تو در تو (Nested Classes):

    cpp
     
    class Outer {
    public:
        class Inner {
        public:
            static void msg() { cout << "Nested!"; }
        };
    };
    
    int main() {
        Outer::Inner::msg(); // "Nested!"
    }
  3. در قالب‌ها (Templates):

    cpp
     
    template<typename T>
    class TemplateClass {
    public:
        static T data;
    };
    
    template<typename T>
    T TemplateClass<T>::data = T(); // تعریف با ::

جمع‌بندی:

 

کاربرد مثال
اعضای استاتیک کلاس MyClass::staticVar
تعریف توایع خارج کلاس void MyClass::func()
حل تعارض نام‌ها ::globalVar
فضای نام std::coutPhysics::gravity
کلاس‌های پایه در وراثت BaseClass::function()
کلاس‌های تو در تو Outer::Inner::method()

 

 

در Geant4، عملگر تعیین دامنه (::) به‌طور گسترده در ساختار کدها برای مدیریت کلاس‌ها، توابع و متغیرها استفاده می‌شود. در اینجا چند نمونه کاربردی از کاربرد این عملگر در مثال‌های Geant4 آورده شده است:

۱. تعریف توابع عضو خارج از کلاس

در کلاس‌هایی مانند DetectorConstruction، توابع عضو (مثل سازنده یا توابع مجازی) در فایل‌های .cc با استفاده از :: تعریف می‌شوند:

cpp
 
// در فایل DetectorConstruction.cc
B1DetectorConstruction::B1DetectorConstruction() {
    // سازنده: تعریف هندسه و مواد
}

void B1DetectorConstruction::ConstructSDandField() {
    // تعریف حسگرها و میدان‌ها
}

این رویکرد، خوانایی کد را افزایش می‌دهد و پیچیدگی هدر فایل‌ها (.hh) را کاهش می‌دهد 15.


۲. دسترسی به اعضای استاتیک کلاس

برای متغیرها یا توابع استاتیک (مثل داده‌های فیزیک)، از :: برای تعریف اولیه و دسترسی استفاده می‌شود:

cpp
 
// در فایل PhysicsList.cc
void B1PhysicsList::ConstructParticle() {
    G4Geantino::GeantinoDefinition(); // فراخوانی عضو استاتیک کلاس
}

این روش در PhysicsList برای مدیریت ذرات و فرآیندهای فیزیکی کاربرد دارد 12.


۳. استفاده در فضای نام (Namespace)

از نسخه‌ی ۱۱ Geant4، کلاس‌های مثال‌ها در فضای نام B1، B2 و ... تعریف می‌شوند:

cpp
 
// در فایل exampleB1.cc
using namespace B1; // فعال‌سازی فضای نام B1
auto* runManager = G4RunManagerFactory::Create(); // ایجاد RunManager

دسترسی به کلاس‌هایی مانند ActionInitialization فقط با B1::ActionInitialization امکان‌پذیر است 2.


۴. فراخوانی توابع کلاس پایه در وراثت

در کلاس‌های مشتق‌شده (مثل PrimaryGeneratorAction)، برای فراخوانی توابع کلاس پایه از :: استفاده می‌شود:

cpp
 
void B1PrimaryGeneratorAction::GeneratePrimaries(G4Event* event) {
    G4VPrimaryGeneratorAction::GeneratePrimaries(event); // فراخوانی نسخه پایه
    // ... تولید ذرات
}

این روش در SteppingAction برای جمع‌آوری داده‌های انرژی نیز دیده می‌شود 213.


۵. مدیریت داده‌ها با ScoringManager

برای فعال‌سازی سیستم Score در خروجی‌گیری داده‌ها، کلاس G4ScoringManager با :: فراخوانی می‌شود:

cpp
 
// در فایل main.cc
#include "G4ScoringManager.hh"
G4ScoringManager* scManager = G4ScoringManager::GetScoringManager();

این دستور، شبکه‌بندی (mesh) و ذخیره‌سازی پارامترهایی مانند EnergyDeposit را فعال می‌کند 13.


❗ نکات کلیدی:

  • تفاوت با . و ->:

    • :: برای عناصر کلاس/فضای نام (بدون نیاز به شیء: MyClass::staticVar).

    • . و -> برای اعضای شیء (مثل obj.method()15.

  • بهینه‌سازی کد: استفاده از :: در تعریف خارج از کلاس، زمان کامپایل را کاهش می‌دهد.

  • خطاهای رایج: عدم استفاده از :: هنگام تعریف توابع عضو منجر به خطای لینکر می‌شود.

برای آزمایش این موارد، مثال B1 در مسیر basic/B1/ Geant4 به‌عنوان نقطه شروع توصیه می‌شود