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

Lecture 6 & 7: Inheritance

المحاضرتان 6 و 7: الوراثة (Inheritance)

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

Slide 3: مفهوم الوراثة (What is Inheritance?)

Slide 3

مبدأ الـ Inheritance (الوراثة) هو واحد من أهم عواميد الـ OOP. الفكرة ببساطة إنك بدل ما تبني كلاس جديد من الصفر، إنت بتورث كلاس تاني موجود بالفعل وتاخد كل الخصائص (Attributes) والدوال (Methods) بتاعته على الجاهز، وتزود عليهم الحاجات الجديدة بتاعتك.

عشان كده عندنا مصطلحين أساسيين:

  • Base Class (الكلاس الأب/الأساسي): الكلاس القديم اللي هنورث منه (زي كلاس Employee).
  • Derived Class (الكلاس الابن/المشتق): الكلاس الجديد اللي بياخد خصائص الأب ويزود عليها (زي كلاس Manager).

Slide 4: علاقة الـ Is-A (The "Is-A" Relationship)

Slide 4

إمتى نستخدم الوراثة؟ بنستخدمها لما تكون العلاقة بين التو كلاسس علاقة "هو عبارة عن" أو (Is-A).

أمثلة:

  • السيارة (Car) Is-A مركبة (Vehicle). إذن Car تورث من Vehicle.
  • المدير (Manager) Is-A موظف (Employee). إذن Manager يورث من Employee.
  • الكلب (Dog) Is-A حيوان (Animal). إذن Dog يورث من Animal.
💡 الفائدة الأساسية (Code Reusability): الوراثة بتوفر علينا كتابة الكود المكرر. بدل ما نكتب دالة (يمشي) لكل الحيوانات، بنكتبها مرة واحدة في الأب (Animal)، وكل الأبناء بيورثوها أوتوماتيك!

Slide 6: طريقة كتابة الوراثة (Inheritance Syntax)

Slide 6

عشان نخلي كلاس يورث من كلاس تاني في الـ C++، بنستخدم النقطتين فوق بعض : (Colon).

// 1. Base Class (Parent) class Shape { public: void setWidth(int w) { width = w; } void setHeight(int h) { height = h; } protected: int width; int height; }; // 2. Derived Class (Child) inheriting from Shape class Rectangle : public Shape { public: int getArea() { return (width * height); // It can use width & height because it inherited them! } };
  • الكلاس Rectangle اتكتب جنبه : public Shape. ده معناه إنه بيورث كلاس Shape وراثة عامة.
  • الابن Rectangle قدر يستخدم المتغيرات width و height اللي موجودين في الأب مع إنه هو نفسه معندهوش المتغيرات دي!

Slide 10: الكلمة السحرية (The 'protected' Access Modifier)

Slide 10

إحنا عارفين الـ public (أي حد يشوفه) والـ private (محدش يشوفه غير الكلاس نفسه).

الوراثة جابت معاها نوع تالت اسمه protected (محمي).

الـ protected بيشتغل إزاي؟

  • بالنسبة للـ main() والناس اللي بره: هو زيه زي الـ private بالظبط (ممنوع اللمس).
  • بالنسبة للكلاسات الأبناء (Derived Classes): هو زيه زي الـ public يقدروا يستخدموه ويعدلوا فيه براحتهم!

يعني ده مستوى حماية "عائلي"، الأب بيسمح لولاده بس يوصلوا لحاجته، لكن الغريب لأ.

Quiz 1: Inheritance Basics & Protected

1. What is the primary advantage of using Inheritance in OOP?

2. Which access specifier should be used in a Base class if you want the data to be hidden from the `main()` function, but fully accessible to its Derived (child) classes?

Slide 13: ترتيب البناء والهدم في الوراثة (Constructors & Destructors Order)

Slide 13

لما تعمل Object من الكلاس الابن (Derived)، هل الابن بيتبني الأول ولا الأب؟ (سؤال امتحان مؤكد).

المنطق بيقول: مفيش ابن بيتولد قبل أبوه!

  • أثناء الإنشاء (Constructors): الكومبايلر بيبدأ بتشغيل Constructor الكلاس الأب (Base) الأول، وبعدين يخلص وينزل يشغل Constructor الكلاس الابن (Derived).
  • أثناء الهدم (Destructors): بنعكس القاعدة (LIFO)! الابن هو اللي بيموت ويتهد الأول، وبعدين الأب يتهد بعده. (الـ Derived Destructor بيشتغل قبل الـ Base Destructor).

Slide 16: تمرير المتغيرات لأباء (Passing Arguments to Base Constructor)

Slide 16

بما إن الأب بيتبني الأول، طب لو الـ Constructor بتاع الأب ده بياخد Parameters (مش Default)؟ إزاي الابن يبعتله الـ Parameters دي وهو بيتبني؟

بنستخدم طريقة اسمها Initialization List (قائمة التهيئة). بنحط نقطتين : بعد Constructor الابن، وننادي على Constructor الأب ونديله قيمه.

class Parent { public: Parent(int x) { cout << "Parent built with " << x << endl; } }; class Child : public Parent { public: // Child Constructor passing 'p' to Parent Constructor BEFORE its own body Child(int p, int c) : Parent(p) { cout << "Child built with " << c << endl; } }; int main() { Child obj(10, 20); // 10 goes to Parent, 20 stays in Child }

Slide 19: تعدي الدوال (Function Overriding)

Slide 19

الـ Overriding (مش الـ Overloading!) بيحصل في الوراثة بس.

يعني إيه؟ يعني الأب عنده دالة اسمها print() بتطبع حاجة معينة، بس الابن مش عاجبه كلام أبوه وعايز يغيره! فالابن بيعمل دالة بنفس الاسم ونفس الـ Parameters بالظبط print() جوا الكلاس بتاعه.

لما تعمل Object من الابن وتنادي print()، الكومبايلر بيتجاهل دالة الأب وبيشغل دالة الابن (الابن بيطغى على الأب).

Slide 20: الوراثة المتعددة (Multiple Inheritance)

Slide 20

في الـ C++، الابن يقدر يورث من أكتر من أب في نفس الوقت! (دي ميزة مش موجودة في لغات تانية زي Java).

يعني ممكن نعمل كلاس SmartPhone يورث من كلاس Camera وكلاس Phone في نفس الوقت!

// Base 1 class Camera { ... }; // Base 2 class Phone { ... }; // Derived Class inheriting from BOTH! class SmartPhone : public Camera, public Phone { // Has features of both a camera and a phone };

Slide 25: مشكلة الغموض (Ambiguity in Multiple Inheritance)

Slide 25

الوراثة المتعددة بتعمل مشكلة خطيرة اسمها Ambiguity (الغموض).

تخيل كلاس الابن (SmartPhone) وارث من (Camera) ومن (Phone)، والاتنين الأبهات عندهم دالة بنفس الاسم اسمها turnOn()! لما الابن يقول s.turnOn()، الكومبايلر هيتلخبط ومش هيبقى عارف يشغل الدالة بتاعة الكاميرا ولا بتاعة التليفون!

الحل (Resolution): إننا نحدد اسم الكلاس الأب اللي نقصده باستخدام معامل الـ Scope Resolution ::.

SmartPhone s; // s.turnOn(); // ❌ ERROR: Ambiguous! s.Camera::turnOn(); // ✅ CORRECT: Turn on the camera s.Phone::turnOn(); // ✅ CORRECT: Turn on the phone

Final Quiz: Inheritance Mechanics

1. When creating an object of a Derived class, what is the exact order of execution for Constructors and Destructors?

2. In Multiple Inheritance, if two base classes have a function with the exact same name, and the derived class calls it, an 'Ambiguity Error' occurs. How do you resolve this in C++?

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

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

Question: Explain the concept of Inheritance in C++. Discuss the `protected` access modifier, the order of Constructor/Destructor calls, how to pass arguments to a Base class constructor, and the Ambiguity problem in Multiple Inheritance with its solution.

🖥️ What is the output of the following code?

Q1:

class Base { public: Base() { cout << "B "; } ~Base() { cout << "~B "; } }; class Derived : public Base { public: Derived() { cout << "D "; } ~Derived() { cout << "~D "; } }; int main() { Derived obj; }

Q2:

class Parent { public: void show() { cout << "Parent" << endl; } }; class Child : public Parent { public: void show() { cout << "Child" << endl; } }; int main() { Child c; c.show(); }

✍️ Write a line of code for the following statements

Q1: Declare a class Dog that inherits publicly from a class Animal.

Q2: Write a Derived constructor that passes value x to the Base constructor using an initialization list.

Q3: Declare a class C that inherits from both A and B (Multiple Inheritance).

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

class Shape { protected: int width; public: Shape(int w) { width = w; } }; class Square : public Shape { public: Square(int w) : Shape(w) {} int area() { return width * width; } }; int main() { Square s(4); cout << s.area() << endl; }

a) What is the output?

b) Why is width declared as protected instead of private?

c) Can we write cout << s.width; in main()?