C++: النطاق والعمر

آخر تحديث: 2026-08-26

المتغيرات ليست "قابلة للوصول من كل مكان بمجرد تعريفها."

بعض المتغيرات يمكن استخدامها فقط داخل زوج من الأقواس، وبعضها يمكن استخدامه في جميع الدوال، وبعضها لا يزال "يتذكر" قيمته السابقة بعد انتهاء الدالة.

هذا هو النطاق والعمر.



1. النطاق

النطاق هو المدى الذي يمكن فيه الوصول إلى متغير.

(1) 1.1 ثلاثة أنواع من النطاق

نوع النطاق موقع التعريف مدى الوصول
نطاق محلي داخل دالة من التعريف حتى نهاية الدالة
نطاق عام خارج جميع الدوال من التعريف حتى نهاية الملف (الملفات الأخرى يمكنها الوصول بـ extern)
نطاق كتلة داخل كتلة عبارة (مثل if، for) من التعريف حتى نهاية الكتلة

▶ مثال 1: المتغيرات المحلية مقابل المتغيرات العامة (صعوبة ⭐)

TEXT 📖 للعرض فقط
#include <iostream>

int gGlobalVar = 100; // Global variable

void foo() {
 int localVar = 5; // Local variable
 std::cout << "foo: localVar = " << localVar << std::endl;
 std::cout << "foo: gGlobalVar = " << gGlobalVar << std::endl;
}

int main() {
 foo();
 // std::cout << localVar << std::endl; // ❌ Error: localVar declared in foo, not visible in main
 std::cout << "main: gGlobalVar = " << gGlobalVar << std::endl; // ✅ Global variable accessible everywhere
 return 0;
}

الخرج:

TEXT 📖 للعرض فقط
foo: localVar = 5
foo: gGlobalVar = 100
main: gGlobalVar = 100

💡 نقطة مهمة: عندما يكون لمتغير محلي ومتغير عام نفس الاسم، المتغير المحلي يأخذ الأسبقية (قاعدة القرب).

CPP
#include <iostream>

int x = 100; // Global variable

int main() {
 int x = 5; // Local variable (same name as global variable)
 std::cout << "x = " << x << std::endl; // Output 5 (local variable takes priority)
 std::cout << "::x = " << ::x << std::endl; // Output 100 (use :: to access global variable)
 return 0;
}


2. نطاق الكتلة

المتغيرات المُعرَّفة داخل كتل عبارات مثل if، for، while يمكن استخدامها فقط داخل الكتلة.

TEXT 📖 للعرض فقط
#include <iostream>

int main() {
 if (true) {
 int blockVar = 5; // Block scope
 std::cout << "Inside block: blockVar = " << blockVar << std::endl;
 }
 // std::cout << blockVar << std::endl; // ❌ Error: blockVar does not exist outside block
 return 0;
}

💡 نصيحة: متغير حلقة for (مثل int i = 0) لديه أيضًا نطاق كتلة. منذ C++11، يُنصح بتعريف متغيرات الحلقة داخل عبارة for ليكون نطاقها محدودًا بالحلقة.



3. العمر

العمر هو المدة من "ميلاد" المتغير حتى "وفاته".

فئة التخزين العمر النطاق الكلمة المفتاحية
متغير تلقائي يُولد عند استدعاء الدالة، يموت عند انتهائها محلي (افتراضي)
متغير محلي ساكن يُولد عند بدء البرنامج، يموت عند انتهائه محلي static
متغير عام يُولد عند بدء البرنامج، يموت عند انتهائه عام (افتراضي)
متغير عام ساكن يُولد عند بدء البرنامج، يموت عند انتهائه نطاق الملف static

(1) 3.1 المتغيرات التلقائية (الافتراضية)

CPP
#include <iostream>

void foo() {
 int x = 5; // Automatic variable (default)
 std::cout << "x = " << x << std::endl;
 x++; // Modify x
 std::cout << "x = " << x << std::endl;
}

int main() {
 foo(); // Output:x = 5, x = 6
 foo(); // Output:x = 5, x = 6(x recreated)
 return 0;
}

💡 نقطة مهمة: المتغيرات التلقائية تُنشأ عند استدعاء الدالة وتُدمر عند انتهائها. عند استدعاء الدالة مرة أخرى، يُعاد إنشاء المتغير (قيمته لا تُحفظ).

(2) 3.2 المتغيرات المحلية الساكنة (static)

TEXT 📖 للعرض فقط
#include <iostream>

void foo() {
 static int x = 5; // Static local variable (initialized only once)
 std::cout << "x = " << x << std::endl;
 x++; // Modify x
}

int main() {
 foo(); // Output:x = 5
 foo(); // Output:x = 6(x preserved its previous value)
 foo(); // Output:x = 7
 return 0;
}

💡 نقطة مهمة: المتغيرات المحلية static تُهيَّأ مرة واحدة فقط، وهي لا تُدمر عند انتهاء الدالة. عند استدعاء الدالة مرة أخرى، تُحفظ قيمتها.



4. المتغيرات العامة

(1) 4.1 الاستخدام الأساسي

CPP
#include <iostream>

int gCount = 0; // Global variable

void increment() {
 gCount++; // Modify global variable
}

int main() {
 std::cout << "Initial value: gCount = " << gCount << std::endl;
 increment();
 increment();
 std::cout << "After two calls: gCount = " << gCount << std::endl;
 return 0;
}

(2) 4.2 مزايا وعيوب المتغيرات العامة

المزايا العيوب
جميع الدوال يمكنها الوصول إليها تكسر التغليف (أي دالة يمكنها تعديلها)
لا حاجة لتمرير المعلمات تجعل البرنامج صعب الفهم (غير واضح من عدّله)
تحتاج قفلًا في كود متعدد الخيوط (ستُغطى لاحقًا)

💡 نصيحة: تجنب المتغيرات العامة قدر الإمكان! إذا كانت دوال متعددة تحتاج مشاركة البيانات، مررها عبر المعلمات.



5. المتغيرات العامة الساكنة

(1) 5.1 الاستخدام الأساسي

TEXT 📖 للعرض فقط
// file1.cpp
static int sFileVar = 5; // Static global variable (only accessible in file1.cpp)

// file2.cpp
extern int sFileVar; // ❌ Error: file2.cpp cannot see sFileVar

💡 نقطة مهمة: المتغيرات العامة static يمكن استخدامها فقط في الملف الحالي — الملفات الأخرى لا يمكنها الوصول إليها عبر extern. هذا يساعد في تجنب تعارضات الأسماء.



6. تطبيق: دالة العد

▶ مثال 2: تنفيذ عداد بمتغير محلي ساكن (صعوبة ⭐⭐)

CPP
#include <iostream>

int getCount() {
 static int count = 0; // Static local variable
 count++;
 return count;
}

int main() {
 std::cout << "No. " << getCount() << " time call" << std::endl;
 std::cout << "No. " << getCount() << " time call" << std::endl;
 std::cout << "No. " << getCount() << " time call" << std::endl;
 return 0;
}
▶ جرّب الكود

الخرج:

TEXT 📖 للعرض فقط
No. 1 time call
No. 2 time call
No. 3 time call

💡 نصيحة: هذه التقنية شائعة الاستخدام في "دوال المصانع" و"نمط المفرد" وسيناريوهات أخرى (ستُغطى لاحقًا).



7. الأخطاء الشائعة

(1) 7.1 الوصول إلى متغيرات خارج نطاقها

مثال خطأ:

TEXT 📖 للعرض فقط
#include <iostream>

int main() {
 if (true) {
 int x = 5;
 }
 std::cout << x << std::endl; // ❌ Error: x does not exist outside if block
 return 0;
}

رسالة خطأ المترجم:

TEXT 📖 للعرض فقط
error: 'x' was not declared in this scope

(2) 7.2 نسيان كتابة static

مثال خطأ:

CPP
#include <iostream>

void foo() {
 int x = 0; // ❌ Forgot to write static
 x++;
 std::cout << "x = " << x << std::endl;
}

int main() {
 foo(); // Output:x = 1
 foo(); // Output:x = 1(Expected 2)
 return 0;
}

▶ مثال 3: المتغيرات المحلية مقابل متغيرات نطاق الكتلة (صعوبة ⭐)

CPP
#include <iostream>

int globalX = 100; // Global variable

int main() {
    int x = 10; // main function's local variable

    {
        int x = 20; // Block scope variable, shadows outer x
        std::cout << "Inner block x = " << x << std::endl;
        std::cout << "Global x = " << globalX << std::endl;
    }

    std::cout << "Outer block x = " << x << std::endl;

    return 0;
}
▶ جرّب الكود

الخرج:

TEXT 📖 للعرض فقط
Inner block x = 20
Global x = 100
Outer block x = 10

❓ أسئلة شائعة

س ما الفرق بين المتغيرات العامة والمتغيرات العامة الساكنة؟
ج > - المتغيرات العامة: يمكن الوصول إليها من جميع الملفات (باستخدام extern) > - المتغيرات العامة الساكنة: يمكن الوصول إليها فقط داخل الملف الحالي
س لماذا تغيرت قيمة متغيري العام بشكل غامض؟
ج على الأرجح دالة أخرى عدّلته.
س عندما يكون لمتغير محلي ومتغير عام نفس الاسم، كيف أصل إلى المتغير العام؟
ج استخدم عامل حل النطاق ::. > > int x = 100; // Global variable > > int main() { > int x = 5; // Local variable > std::cout << "Local x = " << x << std::endl; // 5 > std::cout << "Global x = " << ::x << std::endl; // 100 > return 0; > } >

📖 ملخص


📝 تمارين

  1. أساسي (صعوبة ⭐): اكتب برنامجًا يحتوي على:

  2. متغير عام gTotal

  3. دالة void addToTotal(int x) تضيف x إلى gTotal

  4. في main، استدعِ addToTotal ثلاث مرات، ثم أخرج gTotal

  5. متوسط (صعوبة ⭐⭐): اكتب دالة int getUniqueId() تُرجع معرفًا فريدًا في كل مرة تُستدعى فيها (تبدأ من 1، تزداد بمقدار 1 في كل مرة).

  6. نفّذها باستخدام متغير محلي ساكن

  7. استدعِها خمس مرات في main وأخرج النتائج

  8. تحدي (صعوبة ⭐⭐⭐): اكتب برنامجًا يحتوي الدوال التالية:

  9. void push(int x): تضيف x إلى مصفوفة عامة

  10. int pop(): تزيل وتُرجع العنصر الأخير من المصفوفة العامة

  11. void printStack(): تطبع جميع العناصر في المصفوفة العامة

استخدم متغيرًا عامًا ساكنًا لتقييد المصفوفة على الملف الحالي فقط (أعلن المصفوفة كـ static).


8. 🚀 الخطوة التالية

الآن بعد أن تعلمت النطاق والعمر، لنتابع إلى المصفوفات والسلاسل النصية (الدرس 15) — التعامل مع قيم متعددة من نفس النوع، وسلاسل C++ النصية.

Web-Tutorial.com

فريق Web-Tutorial التقني

منصة دروس برمجية يديرها عدة مطورين. كل درس يتم كتابته ومراجعته بواسطة مطورين متخصصين في المجال. نعمل على ضمان دقة وموثوقية المحتوى — إذا لاحظت أي مشكلة، فيرجى إخبارنا.

100%