الـ Iterators
جزء من قسم البرمجة كائنية التوجه في رحلة C++ على Coddy. الدرس 72 من 104.
المكررات هي كائنات تعمل كجسر بين الحاويات والخوارزميات. وهي توفر طريقة موحّدة للوصول إلى elements في أي حاوية، بغضّ النظر عن كيفية تخزين تلك الحاوية لـ data داخليًا. فكّر في iterator على أنه مؤشر عام يعرف كيفية التحرك داخل حاوية.
توفّر كل حاوية في STL طريقتَي begin() وend(). يشير مكرّر begin() إلى العنصر الأول، بينما يشير end() إلى الموضع الذي يلي العنصر الأخير - وهو قيمة حارسة تحدد مكان التوقف:
#include <vector>
#include <iostream>
int main() {
std::vector<int> nums = {10, 20, 30};
for (std::vector<int>::iterator it = nums.begin(); it != nums.end(); ++it) {
std::cout << *it << " "; // إلغاء المرجع للحصول على القيمة
}
// المخرجات: 10 20 30
}تُبسّط الكلمة المفتاحية auto تعريفات المكرّرات بشكل كبير:
for (auto it = nums.begin(); it != nums.end(); ++it) {
*it *= 2; // تعديل العناصر من خلال المُكرِّر
}
// nums أصبح الآن {20, 40, 60}تأتي iterators في فئات مختلفة بناءً على إمكاناتها. تدعم المكررات ذات الوصول العشوائي (مثل تلك الموجودة في vector) العمليات الحسابية مثل it + 3 أو it1 - it2.
المكررات ثنائية الاتجاه (من list وmap) يمكنها التحرك إلى الأمام والخلف باستخدام ++ و--. يمكن لـ Forward iterators التحرك في اتجاه واحد فقط.
للاجتياز العكسي، استخدم rbegin() وrend():
for (auto rit = nums.rbegin(); rit != nums.rend(); ++rit) {
std::cout << *rit << " "; // يطبع بالترتيب العكسي
}التحدي
سهللنَبْنِ نظامًا لتتبّع المخزون يستخدم المؤشرات للتنقّل عبر مجموعات من العناصر ومعالجتها. ستتدرّب على استخدام أنواع مختلفة من المؤشرات للتنقّل عبر البيانات بطرق متنوعة.
ستُنظّم التعليمات البرمجية في ملفين:
Inventory.h: عرّف فئةInventoryتدير مجموعة من كميات العناصر المخزّنة فيstd::vector<int>.يجب أن توفّر فئتك الطرق التالية:
addItem(int quantity): تضيف كمية عنصر إلى المخزونprintForward(): تستخدم المؤشرات معbegin()وend()لطباعة جميع الكميات مفصولة بمسافات، متبوعة بسطر جديدprintReverse(): تستخدم المؤشرات العكسية معrbegin()وrend()لطباعة جميع الكميات بترتيب عكسي، مفصولة بمسافات، متبوعة بسطر جديدdoubleAll(): تستخدم المؤشرات للتنقّل عبر المتجه ومضاعفة كل كمية في موضعهاgetTotal(): تستخدم المؤشرات لحساب مجموع جميع الكميات وإرجاعه
استخدم الكلمة المفتاحية
autoعند تعريف المؤشرات للحفاظ على نظافة التعليمات البرمجية.main.cpp: اقرأ أربعة مُدخلات صحيحة، كلٌّ منها في سطر منفصل، تمثّل كميات العناصر.أنشئ كائنًا من
Inventoryوأضف الكميات الأربع كلها. ثم اعرض استخدام المؤشرات من خلال:- طباعة
Forward:متبوعة باستدعاءprintForward() - طباعة
Reverse:متبوعة باستدعاءprintReverse() - طباعة
Total: <sum>باستخدامgetTotal() - استدعاء
doubleAll()لتعديل الكميات - طباعة
After doubling:متبوعة باستدعاءprintForward() - طباعة
New total: <sum>باستخدامgetTotal()
- طباعة
على سبيل المثال، عند استخدام المُدخلات 10 و25 و15 و30:
Forward: 10 25 15 30
Reverse: 30 15 25 10
Total: 80
After doubling: 20 50 30 60
New total: 160يتيح لك هذا التحدي التدرّب على قراءة العناصر من خلال المؤشرات (للطباعة والجمع) وتعديل العناصر من خلال المؤشرات (للمضاعفة). وسترى أيضًا كيف تجعل المؤشرات العكسية التنقّل إلى الخلف أمرًا مباشرًا دون الحاجة إلى أي معالجة للفهرس.
جرّب بنفسك
#include <iostream>
#include "Inventory.h"
using namespace std;
int main() {
// اقرأ أربعة مدخلات صحيحة
int q1, q2, q3, q4;
cin >> q1;
cin >> q2;
cin >> q3;
cin >> q4;
// TODO: أنشئ كائن Inventory
// TODO: أضف الكميات الأربع جميعها إلى المخزون
// TODO: اطبع "Forward: " ثم استدعِ printForward()
// TODO: اطبع "Reverse: " ثم استدعِ printReverse()
// TODO: اطبع "Total: " متبوعًا بنتيجة getTotal()
// TODO: استدعِ doubleAll() لتعديل الكميات
// TODO: Print "After doubling: " then call printForward()
// TODO: اطبع "New total: " متبوعًا بنتيجة getTotal()
return 0;
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1أساسيات الـ OOP
الملفات الخارجيةبناء وتجميع (Compilation) لغة C++ملفات الـ Header وملفات الـ Sourceالـ Namespaces والـ Scopeمقدمة في الـ OOP في C++الـ Classes مقابل الـ Objectsالمؤشر 'this'الـ Methods (الدوال الأعضاء)الـ Attributes (بيانات الأعضاء)أساسيات الـ Ctors والـ Dtorsمراجعة - آلة حاسبة بسيطة4خصائص الـ Class
أعضاء الـ Instance مقابل الـ Staticدوال الـ Getters والـ Settersدوال الأعضاء الثابتة (Const)الكلمة المفتاحية Mutableالدوال والمتغيرات الساكنة (Static)الدوال والفئات الصديقة (Friend)مراجعة - مدير الحساب البنكي7الوراثة
الوراثة الأساسيةمستويات الوصول في الوراثةترتيب استدعاء الـ Ctor والـ Dtorإعادة تعريف الدوال (Method Overriding)الدوال الافتراضية والـ VTableالوراثة المتعددةالوراثة الافتراضيةمراجعة - هيكلية الموظفين10نظرة عامة على STL
نظرة عامة وفلسفة STLحاويات STLالـ Iteratorsخوارزميات STLالـ Functors وتعبيرات Lambdaمراجعة - تكرار الكلمات13أنماط التصميم - الجزء الأول
مقدمة في أنماط التصميمنمط Singletonنمط Factory و Abstract Factoryنمط Builderنمط Observerنمط Strategy2إدارة الذاكرة
ذاكرة Stack مقابل Heapالمؤشرات والمراجعالذاكرة الديناميكية (new/delete)المؤشرات الذكية في C++RAII في C++مراجعة - مدير المصفوفات الديناميكية5التغليف (Encapsulation)
محددات الوصول في C++محددات الوصول بشكل متعمقإخفاء المعلوماتStruct مقابل Classالأصناف المتداخلة والداخليةمراجعة - نظام سجلات الطلاب8تعدد الأشكال (Polymorphism)
تعدد الأشكال: وقت التجميع مقابل وقت التشغيلالتحميل الزائد للدوال (Function Overloading)مراجعة الدوال الافتراضية (Virtual Functions)الدوال الافتراضية البحتة (Pure Virtual Functions)الأصناف المجردة (Abstract Classes)تصميم الواجهات (Interface) في C++التحويل الديناميكي (Dynamic Casting) و RTTIملخص - حاسبة الأشكال11مفاهيم OOP المتقدمة
التركيب مقابل الوراثةالـ Mixins عبر CRTPنمط Pimplمحو النوع (Type Erasure)أصناف Enum والأنواع القويةمعالجة الاستثناءات في OOPتسلسلات الاستثناءات المخصصة14أنماط التصميم - الجزء الثاني
نمط الأمرنمط المحولنمط المزيننمط قالب الطريقةنمط الحالةنمط التركيبRAII كنمط3المنشئات والموادم
المنشئ الافتراضيالمنشئ ذو المعاملاتمنشئ النسخمنشئ النقلقوائم تهيئة المنشئالمنشئات المفوضةتعمق في الموادمقاعدة الثلاثة / الخمسة / الصفرمراجعة - فئة String6تحميل العوامل (Operator Overloading)
مقدمة في تحميل العواملتحميل العوامل الحسابيةتحميل عوامل المقارنةعوامل Streamتحميل عامل التعيينتحميل العوامل [] و ()عوامل تحويل النوعمراجعة - Matrix Class9القوالب
قوالب الدوالقوالب الأصنافتخصيص القوالبالقوالب المتغيرةأساسيات SFINAE و Type Traitsمراجعة - الحاويات العامةتدرّب بنفسك: مترجم C++ عبر الإنترنت