الرجوع للقائمة الرئيسية (Back to Home)

Lecture 1: Introduction to OOP Using C++

المحاضرة الأولى: مقدمة في الـ OOP

الشرح التفصيلي لجميع شرائح المحاضرة (Slide-by-Slide) مدعوم بشرح الأكواد سطراً بسطر والتريكات الهامة

Slide 4: لماذا؟ (Why OOP?)

Slide 4

سؤال جوهري ومهم جداً: ليه بندرس الـ OOP أصلاً؟

عشان نجاوب على السؤال ده، لازم نعمل رحلة في تاريخ البرمجة ونعرف إزاي المبرمجين كانوا بيكتبوا كود زمان قبل ما يظهر مفهوم الـ OOP. هنكتشف إن الطرق القديمة كان فيها عيوب خطيرة (Fatal Flaws) ومشاكل كبيرة جداً لما البرامج بتبدأ تكبر وتتعقد. الـ OOP جت كحل جذري عشان تحل كل المشاكل دي وتنظم هيكل الكود بالكامل.

Slide 5: أساليب البرمجة (Styles of Coding)

Slide 5

على مدار تاريخ علوم الحاسب، ظهرت أساليب أو طرق مختلفة لكتابة الكود (Programming Paradigms). الدكتور بيقسمهم لـ 3 مراحل أساسية:

  1. Sequential (Linear) Programming: البرمجة المتسلسلة أو الخطية. كود بيتكتب ورا بعضه سطر سطر من غير أي تنظيم حقيقي.
  2. Procedural Programming: البرمجة الإجرائية. في المرحلة دي، بدأنا ننظم الكود شوية في بلوكات صغيرة اسمها دوال (Functions).
  3. Object Oriented Programming (OOP): البرمجة الكائنية. ودي أحدث وأقوى طريقة اللي هنعتمد عليها في منهجنا.

Slide 6: ما هو البرنامج؟ (What is a program?)

Slide 6

أبسط تعريف لأي برنامج كمبيوتر في الدنيا إنه بيتكون من 3 مكونات أساسية:

  • Inputs (المدخلات): الداتا (Data) اللي بنديها للبرنامج (مثلاً: اسم المستخدم، رقم).
  • Processing (المعالجة): الكود أو العمليات الحسابية والمنطقية اللي البرنامج بيعملها على الـ Data دي عشان يوصل لنتيجة.
  • Outputs (المخرجات): النتيجة النهائية اللي بتظهر لليوزر.
⚠️ تريكة هامة: في أساليب البرمجة القديمة (Linear & Procedural) كنا بنركز بشكل كامل على الـ Processing (الكود والأفعال)، والداتا كانت مرمية ومشتتة في أي حتة في الميموري (Global Data). وده كان السبب الأساسي لمعظم كوارث ومشاكل البرمجة زمان لأن أي دالة كانت ممكن تعدل الداتا دي بالغلط.

Slide 7: العيوب القاتلة للبرمجة الخطية (Four Fatal Flaws of Linear Code)

Slide 7

في الـ Sequential أو Linear Programming، الكود بيكون عبارة عن أوامر ورا بعض. الطريقة دي فيها 4 عيوب قاتلة (4 Fatal Flaws)، وممكن جداً تيجي سؤال في الامتحان:

  • 1. Repetition (التكرار): لو محتاج تنفذ نفس العملية تاني في مكان مختلف، هتضطر تعمل Copy/Paste لنفس سطور الكود. وده بيخلي حجم الكود يكبر على الفاضي ويكون مليان حشو.
  • 2. Disorganization (عدم التنظيم): الكود كله سايح على بعضه في فايل واحد (Spaghetti Code)، مفيش أي هيكلة واضحة. تخيل تدور على غلطة في فايل فيه 10 آلاف سطر!
  • 3. Maintenance Nightmare (كابوس الصيانة): لو حصل مشكلة (Bug) أو حبيت تعدل ميزة معينة، هتلف على الكود كله سطر سطر عشان تعدلها، وممكن جداً وأنت بتعدل حاجة، تبوظ حاجة تانية شغالة.
  • 4. Collaboration Blocker (عائق التعاون): صعب جداً كذا مبرمج يشتغلوا مع بعض في نفس الفايل الطويل ده في نفس الوقت من غير ما يمسحوا شغل بعض (Merge Conflicts).

Quiz 1: Evolution & Flaws of Linear Code

1. Which of the following is considered one of the "Fatal Flaws" of Linear (Sequential) Programming?

2. What is the correct chronological order of the evolution of programming paradigms?

Slide 8: البرمجة الإجرائية (Procedural Programming)

Slide 8

عشان نحل مشاكل البرمجة الخطية (خصوصاً مشكلة الـ Repetition التكرار)، ظهرت الـ Procedural Programming (البرمجة الإجرائية)، زي لغة C كده.

الفكرة هنا إننا بنقسم البرنامج الكبير لبرامج أو مهام صغيرة اسمها Functions (دوال). كل دالة بتعمل وظيفة معينة (مثلاً: دالة بتطبع، دالة بتحسب مجموع). لو احتجنا الوظيفة دي تاني، بنعمل استدعاء للدالة دي باسمها بدل ما نكتب سطور الكود من تاني.

🚨 العيب القاتل في هذه الطريقة (The Fatal Flaw):
البرمجة الإجرائية ركزت جداً على الأفعال (Functions) والمخرجات، بس للأسف أهملت البيانات (Data) بشكل كامل. الداتا كانت مفصولة تماماً عن الدوال اللي بتعالجها، وكانت الداتا متخزنة كـ (Global Variables)، يعني أي دالة في البرنامج ممكن تعدل في أي داتا بالغلط، وده بيعمل كوارث (Data Corruption) في البرامج الكبيرة.

Slide 9: البرمجة الكائنية (Object Oriented Programming)

Slide 9

وهنا بييجي الحل السحري! الـ OOP.

الـ OOP عملت تغيير جذري في التفكير. بدل ما نركز على "الدوال والأفعال" زي ما كنا بنعمل في البرمجة الإجرائية، بقينا نركز على حاجة اسمها الـ Objects (الكائنات) ككيان واحد متكامل.

يعني بدل ما أفكر "إزاي أحسب راتب الموظف؟" (تركيز على الفعل)، بقيت أفكر "أنا عندي كيان كامل اسمه (موظف)، الموظف ده جواه الداتا بتاعته زي الراتب، وجواه هو نفسه القدرة إنه يحسب الراتب بتاعه". التركيز أصبح على محاكاة الأشياء اللي في العالم الحقيقي وتجسيدها جوه الكود.

Slide 10: الكائنات (Objects)

Slide 10

أي كائن (Object) في الدنيا، سواء في العالم الواقعي (زي العربية، الطالب، الكلب) أو في البرمجة، بيتكون من 3 خصائص أساسية جداً (موضع سؤال امتحان أكيد):

  1. State (الحالة): دي الداتا أو الخصائص اللي بتوصف الكائن ده في لحظة معينة. (مثلاً الكلب: لونه، عمره، فصيلته، اسمه). في البرمجة بنسميها (Data Members أو Attributes).
  2. Behavior (السلوك): دي الأفعال والمهام اللي الكائن ده بيقدر يعملها. (مثلاً الكلب: بيهوهو، بيجري). في البرمجة بنسميها (Functions أو Methods).
  3. Identity (الهوية): كل كائن ليه هوية فريدة بتميزه عن أي كائن تاني. الكلب "روي" غير الكلب "بامبو"، حتى لو ليهم نفس اللون ونفس الفصيلة (نفس الـ State). في البرمجة، الـ Identity هي العنوان اللي الكائن ده متخزن فيه في الميموري (Memory Address).

Slide 11: الفشل الثاني: فخ إعادة الاستخدام (The Reusability Trap)

Slide 11

هنا الدكتور بيشرح عيب تاني في البرمجة الإجرائية (Procedural). تخيل إننا بنعمل لعبة كرة قدم.

عندنا دالة بتخلي اللاعب يجري، سميناها playerRun(). وعندنا حكم في الملعب (Referee). هل ينفع من باب "إعادة الاستخدام" إننا نستخدم نفس الدالة دي للحكم ونسميها refereeRun() وناخد نفس الكود بالظبط؟

Conflict (التعارض): سرعة اللاعب ومقدار طاقته غير سرعة الحكم، طريقة الجري (Behavior) مختلفة تماماً. لو اعتمدنا على الدوال بس، هنضطر نعمل دالة منفصلة لكل حاجة في الملعب، والداتا بتاعت السرعة هتكون سايحة (Global) في البرنامج وممكن دالة تجرية اللاعب تغير في سرعة الحكم بالغلط!

ده اسمه Flaw (عيب) في التصميم الإجرائي. الـ Result (النتيجة) هي كود معقد جداً وصعب الحفاظ عليه.

Slide 12: الحل: تجميع البيانات والمنطق (Grouping Data and Logic)

Slide 12

إيه هو الحل للمشكلة اللي فاتت؟

الحل العبقري بتاع الـ OOP هو تجميع الداتا (State) والدوال (Behavior) المرتبطة ببعض (Related) ونحطهم مع بعض ونقفل عليهم في كبسولة واحدة. الكبسولة دي اسمها Class (الفئة/الصنف).

يعني هنعمل Class مستقل اسمه Player، هنحط جواه الداتا بتاعته بس (سرعته هو) وهنحط جواه دواله بس (طريقة جريه هو). وهنعمل Class تاني خالص اسمه Referee جواه الداتا والدوال بتاعته. بالطريقة دي، مستحيل الداتا تدخل في بعضها أو يحصل تداخل.

المعادلة الذهبية (The Golden Equation):
Related Data + Related Functions = CLASS

Slide 13: الفئات (Classes)

Slide 13

طيب يعني إيه Class بالظبط؟

الـ Class هو Blueprint (مخطط هندسي أو نموذج أو قالب). هو مش شيء حقيقي ملموس في الذاكرة، هو مجرد رسمة أو فكرة بتوصف شكل الحاجة (الـ Object) المفروض يكون إيه، إيه البيانات اللي هيشيلها، وإيه الدوال اللي هيعملها.

لما مهندس معماري يبني عمارة، بيرسم الأول الخريطة على الورق. الخريطة دي هي الـ Class. لما العمال يبنوا العمارة فعلاً وتبقى حقيقية وموجودة في الشارع (واخدة مساحة)، العمارة الحقيقية دي هي الـ Object.

بمعنى أصح: الـ Class هو قالب (Template)، والـ Object هو النسخة الفعلية (Instance) اللي اتصبت من القالب ده.

Quiz 2: Objects & Classes

1. Every Object is characterized by three essential elements. What are they?

2. Based on the OOP equation mentioned in the lecture, what does (Related Data + Related Functions) result in?

Slide 14: التفكير في وحدات وكيانات (Thinking in Modules and Entities)

Slide 14

هنا بنشوف مثال عملي للتفكير بأسلوب الـ OOP. لو بعمل لاعب، بجمّع الداتا بتاعته (الاسم، السرعة) والدوال بتاعته (اجري، اشوط) في وحدة أو كيان واحد (Module). الأسلوب ده بيحقق 3 مميزات قوية جداً:

  1. Encapsulation (الكبسلة): حطيت الداتا والدوال في كبسولة واحدة ومقفولة عليهم (وهي الـ Class). الداتا دي بقت مستخبية ومحمية، ومحدش يقدر يعدلها من بره إلا بشروطي.
  2. Navigation (سهولة البحث والتتبع): الكود بقى متنظم جداً. لو في مشكلة (Bug) في حركة اللاعب، أنا مش هلف في الكود كله، أنا هروح مباشرة أفتح الفايل بتاع الـ Player Class بس عشان أصلحها.
  3. Reality Modeling (محاكاة الواقع): الكود بقى شبه الحقيقة. الحقيقة فيها كيان اسمه "لاعب" والكود برضه فيه Object اسمه "لاعب". وده بيسهل جداً فهم الكود وتصميمه.

Slide 15: مرحلة التصميم (Design Phase)

Slide 15

قبل ما نفتح الـ IDE ونكتب كود على الكمبيوتر، لازم نصمم البرنامج الأول على ورق أو ببرامج رسم. مرحلة التصميم دي (Design Phase) من أهم الخطوات في هندسة البرمجيات.

عشان نعبر عن الـ Classes بتاعتنا في مرحلة التصميم، بنستخدم لغة نمذجة موحدة عالمياً اسمها UML (Unified Modeling Language).

رسمة الـ UML Class Diagram بتكون عبارة عن صندوق (Box) متقسم 3 أقسام رئيسية بالترتيب (من أعلى لأسفل):

  1. القسم العلوي (Top Compartment): بنكتب فيه اسم الـ Class (مثلاً: Employee).
  2. القسم الأوسط (Middle Compartment): بنكتب فيه الداتا (Attributes أو Data members).
  3. القسم السفلي (Bottom Compartment): بنكتب فيه الدوال والأفعال (Methods أو Operations).

Slide 16: تطور الكود (The Evolution of Code)

Slide 16

ملخص سريع (Quick Recap) لتطور أساليب البرمجة عشان نأكد على المفهوم:

  1. Sequential (Linear): كود سايح على بعضه، داتا سايحة، مفيش دوال. (فوضى عارمة).
  2. Structured / Procedural: قسمنا الكود لـ Functions بتقدر تتعامل مع الداتا. الداتا نفسها لسه سايحة في البرنامج كله (Global data) ومكشوفة لأي Function. (تنظيم للأفعال مع إهمال حماية البيانات).
  3. OOP: كل حزمة داتا (Data) جبنالها الـ Functions المتعلقة بيها، وقفلنا عليهم جوه صندوق أو كبسولة (Object). الداتا بقت محمية ومخفية عن باقي البرنامج (Encapsulation). (تنظيم وحماية معاً).

Slide 17: مقارنة الأكواد (Code Example Comparison)

Slide 17

الشريحة دي بتوريك شكل الكود الفعلي (Code Snippets) في الـ 3 أساليب:

1. Structured (Linear) Code:

int id = 1; float salary = 5000.0; int id2 = 2; float salary2 = 6000.0; // And so on... unreadable / error prone
  • بنعرف المتغيرات بشكل فردي بدون أي ترابط. كود طويل وممل، عرضة للأخطاء، وصعب جداً في القراءة.

2. Procedural Code:

struct Employee { int id; float salary; }; void printSalary(struct Employee e) { cout << e.salary; }
  • سطر 1-4: عملنا struct لتجميع البيانات مع بعضها (id و salary).
  • سطر 6-8: عملنا دالة printSalary منفصلة تماماً عن الـ struct، بتاخد الـ Employee كـ Parameter عشان تطبع راتبه.
  • النتيجة: الوضع أحسن شوية، بس البيانات لسه مش محمية ومفصولة عن الدوال اللي بتتعامل معاها.

3. Object Oriented (C++):

class Employee { private: int id; float salary; public: void printSalary() { cout << salary; } };
  • سطر 1: عرفنا قالب جديد باستخدام الكلمة المحجوزة class.
  • سطر 2-4: تحت قسم الـ private (السري والمحمي)، حطينا البيانات (id و salary). محدش يقدر يعدلهم من بره الكلاس.
  • سطر 5-8: تحت قسم الـ public (العام والمتاح)، حطينا الدالة printSalary اللي من حقها توصل للبيانات دي وتطبعها.
  • النتيجة: قمة التنظيم والحماية (Encapsulation). الداتا والدوال بقوا حتة واحدة.

Slide 18: شكل فئة الـ UML (UML Syntax of a class)

Slide 18

هنا بنشوف إزاي نحول رسمة الـ UML لكود C++ حقيقي.

class foo { private: int data; public: void memfunc(int d) { data = d; } };
  • سطر 1: بنبدأ بتعريف الكلاس باستخدام class، وبعدها بنكتب اسم الكلاس (هنا اسمه foo)، ونفتح القوس {.
  • محددات الوصول (Access Modifiers):
    • سطر 2 (private:): أي حاجة تتكتب تحتها بتكون سرية ومخفية جوه الكلاس، محدش من بره الكلاس يقدر يوصلها. غالباً بنحط هنا الداتا (Variables).
    • سطر 4 (public:): أي حاجة تتكتب تحتها بتكون متاحة وممكن نستخدمها من أي مكان في البرنامج. غالباً بنحط هنا الدوال.
  • سطر 8: بنقفل قوس الكلاس } ولازم ولازم ولازم نحط في الآخر فاصلة منقوطة (Semicolon ;). نسيانها بيعمل Syntax Error (خطأ شهير جداً في الامتحانات).

Quiz 3: Design & Syntax

1. In a UML Class Diagram, the class box is divided into three compartments. What is the correct order from top to bottom?

2. What is the role of the private access modifier in a C++ class definition?

3. What is the required syntax to correctly terminate a class definition in C++?

Slide 19: مقارنة بين الفئة والكائن (Class vs Object)

Slide 19

جدول مقارنة في غاية الأهمية (بييجي في الامتحانات كتير) بيوضح الفرق الجوهري بين الـ Class والـ Object:

  • Class (الفئة):
    • هو الـ Blueprint (الخريطة، القالب، أو النموذج).
    • بيعرف شكل الداتا إيه والدوال إيه. مجرد تعريف نظري (Definition).
    • مهم جداً: الـ Class مبيسحبش أي مساحة من الـ Memory (Does NOT allocate memory space). هو مجرد حبر على ورق.
  • Object (الكائن):
    • هو الـ Instance (النسخة الفعلية أو الكيان الحقيقي اللي اتعمل من القالب ده).
    • هو ده الشيء الحقيقي اللي موجود وبيحتوي على القيم الفعلية (Actual values) بتاعت الداتا.
    • مهم جداً: الـ Object هو اللي بياخد ويسحب مساحة فعلية في الميموري أول ما يتم إنشاؤه.

Slide 20: مثال على الفئة والكائن (Example of Class & Object)

Slide 20

تطبيق عملي: لو قررنا نعمل Class للموظف (Employee).

  • الداتا (State / Attributes): محتاجين رقم تعريفي ID، اسم Name، وراتب Salary.
  • الأفعال (Behavior / Methods): محتاجين دالة تملى الداتا دي getData()، ودالة تطبع وتعرض الداتا دي displayInfo().

لو عملنا Object من الكلاس ده (يعني عينا موظف حقيقي) وسميناه emp1، ممكن نديله القيم الفعلية دي: ID=100, Name="ABC", Salary=10000. وكده بقى عندنا Object عايش في الميموري بياخد مساحة حقيقية.

Slide 21: رسمة UML للموظف (UML Class Diagram for Employee)

Slide 21

دي رسمة الـ UML الهندسية للمثال اللي فات (ودايماً بتطلب في المسائل):

  • القسم العلوي: مكتوب فيه Employee (اسم الكلاس).
  • القسم الأوسط (الداتا): مكتوب فيه:
    - empid: int
    - empname: string
    - salary: float
    ملاحظة هامة: علامة الناقص - المكتوبة قبل المتغير في الـ UML معناها إن الـ Access Modifier هو private (محمي ومخفي).
  • القسم السفلي (الدوال): مكتوب فيه:
    + getdata(): void
    + Displayinfo(): void
    ملاحظة هامة: علامة الزائد + المكتوبة قبل الدالة في الـ UML معناها إن الـ Access Modifier هو public (عام ومتاح).

Slide 22: المرحلة الثانية - التنفيذ (Phase 2: Implementation Phase)

Slide 22

بعد ما خلصنا مرحلة التصميم ورسمنا الـ UML على الورق، بندخل دلوقتي في Phase 2: Implementation Phase، أو مرحلة كتابة الكود الفعلي.

في المرحلة دي، وظيفتنا إننا نفتح برنامج الـ IDE ونترجم رسمة الـ UML دي لسطور كود فعلية بلغة C++ عشان الكمبيوتر يفهمها ويشغلها.

Slide 23: فصل الواجهة عن التنفيذ (Separation of Interface and Implementation)

Slide 23

قاعدة احترافية ومهمة جداً في كتابة الـ OOP، وهي فصل الكود لملفين منفصلين:

  1. Interface (ملف الواجهة): ده ملف الـ Header اللي امتداده .h. في الملف ده بنكتب "إيه اللي الكلاس بيقدر يعمله؟" بنكتب جواه المتغيرات، ورؤوس الدوال بس (Prototypes) من غير ما نكتب تفاصيل الأكواد من جوه.
  2. Implementation (ملف التنفيذ): ده ملف الـ Source اللي امتداده .cpp. في الملف ده بنكتب "إزاي الكلاس بينفذ الحاجات دي؟" بنكتب جواه الأكواد الفعلية وتفاصيل اللوجيك بتاع الدوال.

Slide 24: مُعامل تحديد النطاق (Scope Resolution Operator)

Slide 24

لما نيجي نفتح ملف الـ .cpp عشان نكتب تفاصيل جسم الدالة، الكمبيوتر هيعرف منين إن الدالة دي تابعة للكلاس الفلاني؟

عشان نربط الدالة بالكلاس بتاعها، بنستخدم معامل مهم جداً اسمه Scope Resolution Operator (::) (نقطتين فوق بعض مرتين).

طريقة الكتابة (Syntax):

returnType ClassName::methodName(parameters) { // statements (body of the function); }
  • بنكتب نوع الإرجاع الأول (زي void).
  • بعدين اسم الكلاس اللي الدالة دي تابعه ليه.
  • بعدين الـ Scope Resolution Operator ::. ده اللزق اللي بيربط الدالة بالكلاس.
  • بعدين اسم الدالة ونفتح أقواس الـ Parameters ونكتب الكود جوه الأقواس {}.

Slide 25: مثال عملي بالكود (Employee code example)

Slide 25

دي صورة بتوريك الملفين جنب بعض بشكل عملي لتطبيق كلاس الـ Employee:

ملف الواجهة: Employee.h (على الشمال)

class Employee { private: int empid; string empname; float salary; public: void getdata(); void Displayinfo(); };
  • حطينا رؤوس الدوال (Prototypes) getdata() و Displayinfo() وحطينا في آخرهم ; بدون أي أكواد تفصيلية.

ملف التنفيذ: Employee.cpp (على اليمين)

#include "Employee.h" void Employee::getdata() { empid = 100; empname = "ABC"; salary = 10000.0; } void Employee::Displayinfo() { cout << "Employee Id : " << empid << endl; cout << "Employee Name : " << empname << endl; cout << "Employee Salary : " << salary << endl; }
  • عملنا #include "Employee.h" عشان الفايل ده يشوف الكلاس اللي عرفناه هناك.
  • استخدمنا Employee:: قبل اسم كل دالة عشان الكومبايلر يفهم إن الأكواد دي تخص كلاس الموظف. بدون الـ :: الكمبيوتر هيديك إيرور (Error).

Quiz 4: Implementation Phase (C++)

1. In C++, which file is typically used to write the actual body and details (Implementation) of class methods?

2. What is the name of the operator used to define a method outside its class declaration, visually represented as (::)?

3. In a UML Class Diagram, what does the minus sign (-) before a variable name denote, and what is its C++ equivalent?

الملخص الشامل لأهم التريكات (Summary & Pro Tips)

سؤال مقالي متوقع للامتحان (Essay Question)

Question: Discuss the main differences between Procedural Programming and Object-Oriented Programming (OOP). Explain why OOP is considered a better approach for large and complex software systems.

🖥️ What is the output of the following code?

Q1: What is the output of the following code?

class Car { public: string color; void display() { cout << "Color: " << color << endl; } }; int main() { Car c1, c2; c1.color = "Red"; c2.color = "Blue"; c1.display(); c2.display(); }

Q2: What is the output of the following code?

class Counter { private: int count; public: void setCount(int c) { count = c; } int getCount() { return count; } }; int main() { Counter obj; obj.setCount(10); cout << obj.getCount() << endl; }

✍️ Write a line of code for the following statements

Q1: Declare a class called Student with a private integer member called id and a public function called setId.

Q2: Create an object called s1 from the class Student, then call the function setId with the value 101.

Q3: Define the function getGrade() of class Student OUTSIDE the class using the Scope Resolution Operator.

🔍 Based on the following code, answer all the following questions

class Rectangle { private: int length, width; public: void setDimensions(int l, int w) { length = l; width = w; } int getArea() { return length * width; } void display() { cout << "Area = " << getArea() << endl; } }; int main() { Rectangle r; r.setDimensions(5, 3); r.display(); }

a) What are the private data members of the class?

b) How many member functions does the class have? List them.

c) What is the output of the program?

d) Can we write cout << r.length; inside main()? Explain why.