C++: النطاق والعمر
آخر تحديث: 2026-08-26
المتغيرات ليست "قابلة للوصول من كل مكان بمجرد تعريفها."
بعض المتغيرات يمكن استخدامها فقط داخل زوج من الأقواس، وبعضها يمكن استخدامه في جميع الدوال، وبعضها لا يزال "يتذكر" قيمته السابقة بعد انتهاء الدالة.
هذا هو النطاق والعمر.
1. النطاق
النطاق هو المدى الذي يمكن فيه الوصول إلى متغير.
(1) 1.1 ثلاثة أنواع من النطاق
| نوع النطاق | موقع التعريف | مدى الوصول |
|---|---|---|
| نطاق محلي | داخل دالة | من التعريف حتى نهاية الدالة |
| نطاق عام | خارج جميع الدوال | من التعريف حتى نهاية الملف (الملفات الأخرى يمكنها الوصول بـ extern) |
| نطاق كتلة | داخل كتلة عبارة (مثل if، for) |
من التعريف حتى نهاية الكتلة |
▶ مثال 1: المتغيرات المحلية مقابل المتغيرات العامة (صعوبة ⭐)
#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;
}
الخرج:
foo: localVar = 5
foo: gGlobalVar = 100
main: gGlobalVar = 100
💡 نقطة مهمة: عندما يكون لمتغير محلي ومتغير عام نفس الاسم، المتغير المحلي يأخذ الأسبقية (قاعدة القرب).
#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 يمكن استخدامها فقط داخل الكتلة.
#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 المتغيرات التلقائية (الافتراضية)
#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)
#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 الاستخدام الأساسي
#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 الاستخدام الأساسي
// 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: تنفيذ عداد بمتغير محلي ساكن (صعوبة ⭐⭐)
#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;
}
الخرج:
No. 1 time call
No. 2 time call
No. 3 time call
💡 نصيحة: هذه التقنية شائعة الاستخدام في "دوال المصانع" و"نمط المفرد" وسيناريوهات أخرى (ستُغطى لاحقًا).
7. الأخطاء الشائعة
(1) 7.1 الوصول إلى متغيرات خارج نطاقها
مثال خطأ:
#include <iostream>
int main() {
if (true) {
int x = 5;
}
std::cout << x << std::endl; // ❌ Error: x does not exist outside if block
return 0;
}
رسالة خطأ المترجم:
error: 'x' was not declared in this scope
(2) 7.2 نسيان كتابة static
مثال خطأ:
#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: المتغيرات المحلية مقابل متغيرات نطاق الكتلة (صعوبة ⭐)
#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;
}
الخرج:
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; > } >📖 ملخص
- النطاق هو المدى الذي يمكن فيه الوصول إلى متغير (محلي، عام، كتلة)
- العمر هو المدة التي يوجد فيها متغير (تلقائي، ساكن، عام)
- المتغيرات المحلية: تُنشأ عند استدعاء الدالة، تُدمر عند انتهائها
- المتغيرات المحلية الساكنة (
static): تُهيَّأ مرة واحدة فقط، تُحفظ قيمتها بعد انتهاء الدالة - المتغيرات العامة: يمكن الوصول إليها من جميع الدوال، لكن حاول تجنب استخدامها
- المتغيرات العامة الساكنة: يمكن الوصول إليها فقط داخل الملف الحالي
📝 تمارين
-
أساسي (صعوبة ⭐): اكتب برنامجًا يحتوي على:
-
متغير عام
gTotal -
دالة
void addToTotal(int x)تضيفxإلىgTotal -
في
main، استدعِaddToTotalثلاث مرات، ثم أخرجgTotal -
متوسط (صعوبة ⭐⭐): اكتب دالة
int getUniqueId()تُرجع معرفًا فريدًا في كل مرة تُستدعى فيها (تبدأ من 1، تزداد بمقدار 1 في كل مرة). -
نفّذها باستخدام متغير محلي ساكن
-
استدعِها خمس مرات في
mainوأخرج النتائج -
تحدي (صعوبة ⭐⭐⭐): اكتب برنامجًا يحتوي الدوال التالية:
-
void push(int x): تضيفxإلى مصفوفة عامة -
int pop(): تزيل وتُرجع العنصر الأخير من المصفوفة العامة -
void printStack(): تطبع جميع العناصر في المصفوفة العامة
استخدم متغيرًا عامًا ساكنًا لتقييد المصفوفة على الملف الحالي فقط (أعلن المصفوفة كـ static).
- المتغيرات العامة: يمكن الوصول إليها من جميع الدوال في الملف، موجودة من بداية البرنامج حتى نهايته
- المتغيرات المحلية: مرئية داخل كتلة، تُدمر عند انتهاء الكتلة
- المتغيرات المحلية الساكنة: تُهيَّأ مرة واحدة، تُدمر فقط عند انتهاء البرنامج
- فضاءات الأسماء تُعرَّف بـ
namespaceلتجنب تعارضات الأسماء - تصريحات
usingتُدخل أسماء محددة؛ توجيهاتusingتُدخل فضاء أسماء كاملًا
8. 🚀 الخطوة التالية
الآن بعد أن تعلمت النطاق والعمر، لنتابع إلى المصفوفات والسلاسل النصية (الدرس 15) — التعامل مع قيم متعددة من نفس النوع، وسلاسل C++ النصية.