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

Mega Question Bank

🚀 البنك الشامل - جميع أقسام الـ OOP 🚀

مقسّم حرفياً زي المنهج: شامل الـ MCQs، الأكواد، الـ Tracing، ومسائل הـ UML بالأكشن في الـ main متوثقة بالشرح العربي

1. Introduction to OOP

📌 Why OOP, Principles, and Basic UML

Q1. What is the main limitation of Procedural Programming that OOP aims to solve?

👁️ إظهار الإجابة والتفسير
Answer: B) Lack of code organization leading to Spaghetti Code
Explanation:

Procedural programming focuses on functions rather than data, making large codebases hard to maintain.

بالعامية: البرمجة الإجرائية بتركز على الدوال، ولما البرنامج بيكبر الكود بيدخل في بعضه ويبقى Spaghetti code، عشان كدا الـ OOP ظهرت لتنظيم الكود وربط البيانات بالدوال.

Q2. Which of the following describes the 'Bottom-Up' approach of OOP?

👁️ إظهار الإجابة والتفسير
Answer: B) Starting by designing classes and objects, then combining them to build the main program
Explanation:

OOP uses a bottom-up approach: you build the basic entities (classes) first, then use them to construct complex systems.

بالعامية: الـ OOP بتبدأ من تحت لفوق (Bottom-Up). يعني بنصمم الكلاسات والأوبجيكت الأول، وبعدين نجمعهم في الـ main عشان نبني البرنامج الكبير.

Q3. Which of the following is considered a primary BENEFIT of Object-Oriented Programming?

👁️ إظهار الإجابة والتفسير
Answer: B) Code Reusability and Modularity
Explanation:

Through features like inheritance and classes, OOP promotes modular design and code reusability, saving time and reducing bugs.

بالعامية: أكبر فايدة للـ OOP إنها بتخلينا نعيد استخدام الكود (عن طريق الوراثة مثلاً) وإننا نقسم البرنامج لموديولات (كلاسات) منفصلة يسهل صيانتها (Modularity & Reusability).

Q4. True or False?

Data Hiding (Encapsulation) makes it impossible for the user of the class to accidentally corrupt the internal state of the object.

👁️ إظهار الإجابة والتفسير
Answer: True
Explanation:

By making variables private and only exposing controlled setters/getters, the internal state cannot be modified directly.

بالعامية: صح جداً. الكبسلة (Encapsulation) بتخفي البيانات (private) عشان تمنع أي حد يعدل فيها بطريقة غلط من الـ main، ولازم يستخدم دوال محددة زي الـ Setters.

Q5. Design a UML class named 'Rectangle'. It has private width and height. Implement setters, getters, and an area method. Write the UML, then code it with a main() that uses these methods.

Rectangle
-------------------
- width: float
- height: float
-------------------
+ setWidth(w: float): void
+ setHeight(h: float): void
+ getArea(): float
👁️ إظهار الإجابة والتفسير
Answer:
#include  // استدعاء مكتبة الإدخال والإخراج
using namespace std; // استخدام الفضاء المعياري

class Rectangle { // تعريف الكلاس
private: // البيانات الخاصة (مقفول عليها)
    float width; // الطول
    float height; // العرض
public: // الدوال العامة اللي هنستخدمها من بره
    void setWidth(float w) { width = w; } // دالة لإدخال الطول
    void setHeight(float h) { height = h; } // دالة لإدخال العرض
    
    float getArea() { // دالة لحساب المساحة
        return width * height; // ضرب الطول في العرض
    }
};

int main() { // الدالة الرئيسية
    // Action in main!
    Rectangle rect; // إنشاء أوبجيكت من نوع Rectangle
    rect.setWidth(5.5); // تحديد الطول
    rect.setHeight(10.0); // تحديد العرض
    cout << "Area of rectangle is: " << rect.getArea() << endl; // طباعة المساحة
    return 0; // إنهاء البرنامج
}

Explanation:

Basic encapsulation: data is private, accessed only via public setter/getter methods.

بالعامية: تطبيق أساسي على الـ Encapsulation (الكبسلة). خلينا الطول والعرض private ومحدش يقدر يوصلهم في الـ main غير من خلال الدوال الـ public زي الـ set.

Q6. Design a UML for a 'Bank' system. It has a balance. Implement a constructor and a withdraw method that checks if balance is sufficient. Test this logic in main().

Bank
-------------------
- balance: double
-------------------
+ Bank(initial: double)
+ withdraw(amount: double): bool
👁️ إظهار الإجابة والتفسير
Answer:
#include  // مكتبة الطباعة
using namespace std;

class Bank { // تعريف كلاس البنك
private: 
    double balance; // الرصيد (مخفي)
public:
    Bank(double initial) { // Constructor بيستقبل الرصيد الافتتاحي
        balance = initial; // تعيين الرصيد
    }
    bool withdraw(double amount) { // دالة السحب
        if (amount <= balance) { // لو المبلغ المطلوب أقل من أو يساوي الرصيد
            balance -= amount; // اخصم المبلغ
            cout << "Withdrawal successful. New balance: " << balance << endl; // طباعة نجاح
            return true; // السحب تم
        } else { // لو الرصيد مش مكفي
            cout << "Insufficient funds!" << endl; // طباعة رسالة فشل
            return false; // السحب اترفض
        }
    }
};

int main() {
    Bank myBank(1000.0); // فتح حساب بـ 1000
    myBank.withdraw(400.0); // سحب 400 (هينجح)
    myBank.withdraw(800.0); // سحب 800 (هيفشل لأن الباقي 600)
    return 0; // إنهاء
}

Explanation:

The logic checks if the requested amount is available before deduction, demonstrating how classes protect their state.

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

2. Objects & Classes

📌 Access Modifiers, Constructors, Destructors, Setters & Getters

Q7. What is the primary difference in default Access Modifiers between a `struct` and a `class` in C++?

👁️ إظهار الإجابة والتفسير
Answer: C) Default access in struct is public, in class it is private
Explanation:

If you don't write `public:` or `private:`, a struct assumes everything is public, while a class assumes everything is private.

بالعامية: في الـ struct لو مكتبتش حاجة كل حاجة بتبقى مكشوفة (public). لكن الكلاس مصمم عشان يخفي البيانات فبيعتبر أي حاجة مش مكتوب قبلها modifier إنها (private).

Q8. True or False?

The main reason to use Setters (Mutators) instead of making variables public is to validate data before changing it.

👁️ إظهار الإجابة والتفسير
Answer: True
Explanation:

Setters allow us to add 'if' statements to prevent bad data (like negative age or invalid passwords) from entering the object.

بالعامية: صح جداً. الـ Setter مش مجرد دالة بتاخد قيمة تحطها في متغير وخلاص، فايدتها الأساسية إنك تقدر تحط شروط (if) جواها وتمنع المستخدم إنه يدخل داتا غلط (زي عمر بالسالب مثلاً).

Q9. True or False?

If you define a parameterized constructor, the compiler still generates a default constructor for you automatically.

👁️ إظهار الإجابة والتفسير
Answer: False
Explanation:

Once you define ANY constructor, the compiler stops generating the default one.

بالعامية: غلط. بمجرد ما بتعمل Constructor بتاعك (حتى لو بـ parameters)، الكومبايلر بيبطل يساعدك ولازم تكتب الـ Default بنفسك لو عاوزه.

Q10. When is the Copy Constructor invoked?

👁️ إظهار الإجابة والتفسير
Answer: D) All of the above
Explanation:

A copy constructor is triggered whenever a completely new object is created from an existing object.

بالعامية: الـ Copy Constructor بيشتغل في كل الحالات دي: لو رجعت أوبجيكت By Value من دالة، أو بعته لدالة By Value، أو لو ساويت أوبجيكت جديد بواحد قديم وقت تعريفه (زي Student s2 = s1).

Q11. What will be printed to the screen?

class Test {
public:
    Test() { cout << "D "; }
    Test(int x) { cout << "P "; }
};
int main() {
    Test t1;
    Test t2(5);
    Test t3(); 
    return 0;
}
👁️ إظهار الإجابة والتفسير
Answer: B) D P
Explanation:

Test t3() is a function declaration (returning a Test object), NOT an object instantiation! It is known as the Most Vexing Parse in C++.

بالعامية: خبيثة جداً جداً! السطر الأول بيطبع D، التاني بيطبع P. السطر التالت `Test t3()` ده مش بيعمل أوبجيكت! الكومبايلر بيفتكره دالة عادية اسمها t3 بترجع أوبجيكت من نوع Test، فمش بيستدعي الـ Constructor خالص.

Q12. Implement all 3 constructors (Default, Parameterized, Copy) and a Destructor for a 'Student' class with an ID and Name. Create objects using all 3 in main().

Student
-------------------
- id: int
- name: string
-------------------
+ Student()
+ Student(i: int, n: string)
+ Student(const s: Student&)
+ ~Student()
+ print(): void
👁️ إظهار الإجابة والتفسير
Answer:
#include 
#include  // مكتبة النصوص
using namespace std;

class Student { // كلاس الطالب
private:
    int id; // رقم الطالب
    string name; // اسم الطالب
public:
    // 1. Default Constructor
    Student() { // الـ Constructor الافتراضي (فاضي)
        id = 0; name = "Unknown"; // قيم ابتدائية
        cout << "Default Constructor Called\n"; // للتأكيد
    }
    
    // 2. Parameterized Constructor
    Student(int i, string n) { // بياخد بارامترز
        id = i; name = n; // تعيين القيم
        cout << "Parameterized Constructor Called\n";
    }
    
    // 3. Copy Constructor
    Student(const Student& s) { // بياخد Reference من أوبجيكت تاني
        id = s.id; // نسخ الـ ID
        name = s.name; // نسخ الاسم
        cout << "Copy Constructor Called\n";
    }
    
    // Destructor
    ~Student() { // الهدّام (بيشتغل لما الأوبجيكت يموت)
        cout << "Destructor Called for " << name << "\n";
    }
    
    void print() { cout << "ID: " << id << " Name: " << name << endl; } // دالة الطباعة
};

int main() {
    Student s1;                  // أوبجيكت فاضي (ينادي Default)
    Student s2(101, "Ahmed");    // أوبجيكت ببيانات (ينادي Parameterized)
    Student s3 = s2;             // أوبجيكت جديد بينسخ من s2 (ينادي Copy)
    
    s3.print(); // طباعة بيانات s3
    return 0; // البرنامج بيقفل والهدام بيشتغل بالعكس (s3 ثم s2 ثم s1)
}

Explanation:

Demonstrates the complete lifecycle of objects. Notice the Copy constructor must take a reference.

بالعامية: المسألة دي بتلم كل أنواع الـ Constructors. في الـ main جربنا نعمل أوبجيكت فاضي (Default)، وأوبجيكت ببيانات (Parameterized)، وأوبجيكت بينسخ من واحد تاني (Copy). وفي النهاية הـ Destructor هيمسحهم بالعكس.

📌 Objects as Arguments, Memory & Const/Static Members

Q13. True or False?

Memory is allocated for a Class when it is defined in the code.

👁️ إظهار الإجابة والتفسير
Answer: False
Explanation:

A class is just a blueprint. NO memory is allocated until an object of that class is created.

بالعامية: غلط! الكلاس مجرد تصميم على ورق (Blueprint) مابياخدش أي ميموري خالص. الميموري بتتحجز أول ما تصنع منه أوبجيكت (Object Creation) في الـ main.

Q14. Why is it highly recommended to pass objects to functions 'By Reference' (e.g., `void func(const Object& obj)`) rather than 'By Value'?

👁️ إظهار الإجابة والتفسير
Answer: B) It avoids the overhead of invoking the copy constructor and copying all data
Explanation:

Passing by value makes a full copy of the object which is slow and consumes memory. Passing by reference just passes the memory address.

بالعامية: تمرير الـ Object للدوال (By Value) بيخلي الكومبايلر يشغل הـ Copy Constructor ويعمل نسخة كاملة من الأوبجيكت بكل اللي فيه وده بيبطئ البرنامج. عشان كده دايماً بنبعته (By Reference &) عشان نبعت مساره بس، وبنحط const لو مش عايزين الدالة تغير فيه.

Q15. True or False?

An inline function guarantees that the compiler will expand it at the call site.

👁️ إظهار الإجابة والتفسير
Answer: False
Explanation:

Inline is only a REQUEST to the compiler. If the function is too complex, contains loops, or is recursive, the compiler ignores the inline request.

بالعامية: غلط. كلمة Inline دي (طلب) بنطلبه من الكومبايلر، بس لو الدالة كانت معقدة أوي أو فيها Loops الكومبايلر هيرفض الطلب ويعتبرها دالة عادية جداً.

Q16. What happens when this code is compiled?

class Number {
    int val;
public:
    Number(int v) { val = v; }
    int getVal() { return val; } // NOT const
};
int main() {
    const Number n(10);
    cout << n.getVal();
    return 0;
}
👁️ إظهار الإجابة والتفسير
Answer: B) Compilation Error
Explanation:

A constant object (`const Number n`) CANNOT call non-const methods. Since `getVal` is not marked as const, the compiler blocks it to protect the object.

بالعامية: عشان الأوبجيكت `n` متعرف إنه ثابت (const)، الكومبايلر بيمنعه إنه يستدعي أي دالة مش متأمنة بكلمة const، عشان خايف إنها تغير قيمته. فلازم نكتب `int getVal() const` عشان يشتغل.

Q17. Which of the following is TRUE about Static Member Functions?

👁️ إظهار الإجابة والتفسير
Answer: C) They can only access static member variables and static functions
Explanation:

Static methods belong to the class level. They do not know about specific objects, so they have no 'this' pointer and can only interact with static variables.

بالعامية: الدوال הـ Static دي بتاعة الكلاس ككل مش بتاعة أوبجيكت معين. فمتقدرش توصل لمتغيرات عادية (لأن مفيش this pointer يعرّفها الأوبجيكت فين)، وتتعامل بس مع الحاجات הـ static زيها.

Q18. Create a 'Point' class with X and Y. Make an inline function to print it. Create a function 'addPoints' that takes two objects and RETURNS a new Point object. Test in main().

Point
-------------------
- x: int
- y: int
-------------------
+ Point(x: int, y: int)
+ inline print() const: void
+ addPoints(p1: Point, p2: Point): Point
👁️ إظهار الإجابة والتفسير
Answer:
#include 
using namespace std;

class Point { // كلاس النقطة
private:
    int x, y; // الإحداثيات
public:
    Point(int xVal, int yVal) { // Constructor
        x = xVal; y = yVal;
    }
    
    // Inline & Const function
    inline void print() const { // دالة Inline وسريعة وكمان Const
        cout << "(" << x << ", " << y << ")\n"; // طباعة النقطة
    }
    
    // Function taking objects and returning an object
    Point addPoints(Point p1, Point p2) { // دالة بتاخد 2 أوبجيكتس
        Point temp(p1.x + p2.x, p1.y + p2.y); // بنجمعهم ونحطهم في أوبجيكت جديد
        return temp; // بنرجع الأوبجيكت الجديد
    }
};

int main() {
    Point p1(3, 4); // النقطة الأولى
    Point p2(1, 2); // النقطة التانية
    
    // Note: Calling via object since it's a member function
    Point p3 = p1.addPoints(p1, p2); // بننادي الدالة عشان تجمعهم
    
    cout << "Result: ";
    p3.print(); // بنطبع النتيجة
    
    return 0; // إنهاء
}

Explanation:

Objects can be passed exactly like normal variables, and returned identically. Const methods guarantee the object's data won't change.

بالعامية: في الـ main بعتنا اتنين أوبجيكتس للدالة `addPoints`، الدالة جمعت الـ X والـ Y وعملت أوبجيكت جديد (temp) ورجعته، واستقبلناه في `p3`. واستخدمنا `inline` عشان نسرع أداء الطباعة.

Q19. Design a 'Car' class. It has a static variable 'totalCars' to track how many cars are created. In main(), create an array of 3 Cars and print the static variable using a static method.

Car
-------------------
- model: string
- static totalCars: int
-------------------
+ Car()
+ Car(m: string)
+ static getTotalCars(): int
+ ~Car()
👁️ إظهار الإجابة والتفسير
Answer:
#include 
#include 
using namespace std;

class Car { // كلاس العربية
private:
    string model; // موديل العربية
    static int totalCars; // متغير Static (مُشترك بين كل العربيات)
public:
    Car() { // Default Constructor
        model = "Default";
        totalCars++; // بنزود عدد العربيات
    }
    Car(string m) { // Parameterized Constructor
        model = m;
        totalCars++; // بنزود عدد العربيات
    }
    
    static int getTotalCars() { // دالة Static عشان ترجع العدد
        return totalCars; // هترجع المتغير الـ static
    }
    
    ~Car() { // Destructor
        totalCars--; // لما عربية تتمسح، ننقص العدد
    }
};

// Static Initialization MUST be outside the class!
int Car::totalCars = 0; // تعريف المتغير הـ Static بره الكلاس ونديله صفر

int main() {
    cout << "Initial Cars: " << Car::getTotalCars() << endl; // بنشوف العدد قبل أي حاجة
    
    // Array of Objects calls Default Constructor 3 times
    Car showroom[3]; // حجزنا مصفوفة فيها 3 عربيات
    
    cout << "Cars after array creation: " << Car::getTotalCars() << endl; // العدد بقى 3
    
    {
        Car temp("BMW"); // عملنا عربية جديدة جوه قوسين Scope
        cout << "Cars inside block: " << Car::getTotalCars() << endl; // العدد بقى 4
    } // الـ Scope خلص، عربية BMW اتمسحت، الهدام نقص العدد
    
    cout << "Cars after block: " << Car::getTotalCars() << endl; // العدد رجع 3 تاني
    
    return 0; // إنهاء
}

Explanation:

Static variables are shared among all instances. They must be initialized globally outside the class.

بالعامية: المتغير الـ static مشترك بين كل العربيات. أول ما عملنا Array فيها 3 عربيات، الـ Constructor اشتغل 3 مرات وزود العدد. ولما الأوبجيكت اللي جوه القوسين مات، الـ Destructor اشتغل ونقص العدد. وطبعنا العدد بدون ما نحتاج أوبجيكت عن طريق `Car::getTotalCars()`.

3. Memory Management

📌 Stack vs Heap & Memory Problems

Q20. What is the difference between `new` in C++ and `malloc()` in C?

👁️ إظهار الإجابة والتفسير
Answer: C) `new` allocates memory AND calls the constructor, `malloc` only allocates raw memory
Explanation:

In OOP, objects must be initialized. `new` ensures the constructor is called automatically after memory is allocated.

بالعامية: دي حتة مهمة جداً! `new` في الـ C++ مش بس بتحجز مكان في الـ Heap، دي كمان بتشغل الـ Constructor عشان تبني الأوبجيكت صح. لكن `malloc` بتاعة الـ C كانت بتحجز ميموري فاضية (زبالة) ومش بتشغل حاجة.

Q21. Which of the following scenarios is the most common cause of a 'Stack Overflow' error?

👁️ إظهار الإجابة والتفسير
Answer: B) Infinite or excessively deep recursion without a base case
Explanation:

The stack has limited size. If a function calls itself infinitely, it fills up the stack memory until it overflows.

بالعامية: الـ Stack مساحته صغيرة نسبياً. لو عملت دالة بتنادي نفسها إلى ما لا نهاية (Recursion بدون شرط توقف) أو عملت مصفوفة حجمها ضخم جداً جوه دالة عادية، الـ Stack بيتملي ويضرب ويديك Error.

Q22. True or False?

A Memory Leak happens when a pointer pointing to dynamically allocated memory goes out of scope without calling `delete`.

👁️ إظهار الإجابة والتفسير
Answer: True
Explanation:

If the pointer disappears, the memory it was pointing to is orphaned and can never be freed.

بالعامية: صح تماماً. لو البوينتر اتمسح من الـ Stack لأنه خلص الـ Scope، الميموري اللي حجزها في הـ Heap هتفضل محجوزة على الفاضي ومفيش أي طريقة نوصلها بيها. وده هو الـ Memory Leak.

Q23. What critical memory error occurs in this code?

void process() {
    int* data = new int[500];
    // processing ...
    data = new int[1000];
    delete[] data;
}
👁️ إظهار الإجابة والتفسير
Answer: B) Memory Leak of 500 integers
Explanation:

The pointer `data` originally pointed to 500 ints. By reassigning it without `delete[]` first, those 500 ints are lost in the Heap forever.

بالعامية: حجزنا 500 مكان، وبعدين البوينتر سابهم ومسك في 1000 مكان تانيين! طب الـ 500 الأوليين دول هيمسحهم إزاي ومفيش بوينتر بيشاور عليهم؟ ضاعوا في الميموري (Memory Leak).

Q24. Create a 'DynamicArray' class that allocates a dynamic int array in its constructor and deletes it in its destructor. Test in main() by dynamically allocating the class object itself.

DynamicArray
-------------------
- size: int
- arr: int*
-------------------
+ DynamicArray(s: int)
+ fillData(): void
+ ~DynamicArray()
👁️ إظهار الإجابة والتفسير
Answer:
#include 
using namespace std;

class DynamicArray { // الكلاس
private:
    int size; // حجم المصفوفة
    int* arr; // بوينتر هيشاور على المصفوفة في الـ Heap
public:
    DynamicArray(int s) { // Constructor
        size = s; // نسجل الحجم
        arr = new int[size]; // بنحجز الميموري في הـ Heap
        cout << "Array of size " << size << " created in Heap.\n";
    }
    
    void fillData() { // دالة تعبئة البيانات
        for(int i=0; i// Loop لملء الأرقام
            arr[i] = i * 10; // بنملا المصفوفة
        }
        cout << "First element: " << arr[0] << ", Last: " << arr[size-1] << endl;
    }
    
    ~DynamicArray() { // Destructor الأهم
        delete[] arr; // لازم نمسح المصفوفة عشان نمنع الـ Memory Leak!
        cout << "Array memory freed.\n";
    }
};

int main() {
    // Dynamically allocating the OBJECT itself in the Heap!
    DynamicArray* myArr = new DynamicArray(50); // بنحجز الأوبجيكت نفسه في الـ Heap بـ new
    
    myArr->fillData(); // بننادي دالة التعبئة
    
    // If we don't call delete, the destructor is NEVER called!
    delete myArr; // خطوة قاتلة: لازم نعمل delete عشان הـ Destructor يشتغل والمصفوفة تتمسح
    
    return 0; // إنهاء
}

Explanation:

A dynamic object must be explicitly deleted. When `delete myArr` is called, the object's destructor runs, which in turn deletes the inner dynamic array.

بالعامية: هنا إحنا حجزنا (أوبجيكت) كامل في الـ Heap باستخدام new. الأوبجيكت ده جواه Constructor بيحجز (مصفوفة) في الـ Heap بردو! لو معملناش `delete myArr` في الـ main، الهدّام مش هيشتغل والمصفوفة مش هتتمسح والدنيا هتبوظ.

Q25. Implement Deep Copy vs Shallow Copy. Create a 'StringBox' class holding a dynamic char pointer. Implement a Custom Copy Constructor to avoid dangling pointers. Test it in main().

StringBox
-------------------
- text: char*
-------------------
+ StringBox(t: const char*)
+ StringBox(const other: StringBox&)  << Deep Copy
+ ~StringBox()
+ print(): void
👁️ إظهار الإجابة والتفسير
Answer:
#include 
#include  // مكتبة التعامل مع الحروف
using namespace std;

class StringBox { // كلاس الصندوق
private:
    char* text; // بوينتر لكلمة
public:
    // Regular Constructor
    StringBox(const char* t) {
        text = new char[strlen(t) + 1]; // بنحجز مكان على قد الكلمة بالضبط في הـ Heap
        strcpy(text, t); // بننسخ الكلمة في الميموري
    }
    
    // Deep Copy Constructor!
    StringBox(const StringBox& other) { // الـ Copy Constructor الحقيقي عشان يحل مشكلة الـ Shallow
        text = new char[strlen(other.text) + 1]; // بنحجز مكان جديد خالص (NEW memory)
        strcpy(text, other.text); // بننسخ الداتا نفسها مش مجرد الـ Address
        cout << "Deep copy performed.\n";
    }
    
    ~StringBox() { // الهدام
        delete[] text; // بيمسح الميموري بتاعته بس (بدون تدخل في الميموري بتاعة الأوبجيكتس التانية)
    }
    
    void print() { cout << "Text: " << text << endl; } // الطباعة
};

int main() {
    StringBox box1("Hello OOP"); // الأوبجيكت الأول
    // This calls the copy constructor. If it was shallow, both would point to same memory!
    StringBox box2 = box1; // الأوبجيكت التاني بيعمل Deep Copy من الأول
    
    box1.print();
    box2.print();
    // لما الـ main يخلص، الاتنين Destructors هيشتغلوا ويمسحوا أماكن منفصلة بسلام.
    return 0;
}

Explanation:

Without a deep copy constructor, both objects' pointers would hold the same memory address. Deleting one would make the other a dangling pointer, crashing the program when it's deleted twice.

بالعامية: لو معملناش Copy Constructor بـ Deep Copy، الكومبايلر هينسخ عنوان البوينتر بس! ولما البرنامج يخلص، الاتنين Destructors هيحاولوا يمسحوا نفس العنوان من الـ Heap والبرنامج هيضرب (Double Free). هنا إحنا حجزنا مكان جديد خالص للنسخة ونقلنا فيه الداتا.

4. Inheritance

📌 Types, Access Specifiers & Order

Q26. True or False?

Hybrid Inheritance is a combination of more than one type of inheritance (e.g., combining Multilevel and Multiple inheritance).

👁️ إظهار الإجابة والتفسير
Answer: True
Explanation:

Yes, whenever a class structure mixes different inheritance models (like a diamond shape), it is termed hybrid inheritance.

بالعامية: صح. الوراثة الهجينة (Hybrid) هي لما البرنامج بتاعنا يبقى فيه خلطة من الوراثة، يعني مثلاً فيه جزء Multi-level شغال وجزء Multiple، فبنسميها مهجنة.

Q27. What happens in 'private inheritance'?

👁️ إظهار الإجابة والتفسير
Answer: A) Public and protected members of Base become private in Derived
Explanation:

In private inheritance, the derived class can use the base methods internally, but they are completely hidden from the outside world (the main).

بالعامية: لما الكلاس الابن يورث بشكل `private`، بياخد كل حاجة `public` و `protected` من الأب يحبسها جواه ويخليها `private` عنده هو، وبالتالي محدش في הـ main بيقدر يشوفها.

Q28. True or False?

In inheritance, the derived class constructor runs BEFORE the base class constructor.

👁️ إظهار الإجابة والتفسير
Answer: False
Explanation:

The Base class (the foundation) is always constructed BEFORE the Derived class.

بالعامية: غلط تماماً. البناء بيبدأ من الأب (الأساس) وبعدين الابن بيكمل عليه. الهدد بس هو اللي بيبدأ بالابن الأول.

Q29. Trace the exact output sequence:

class A {
public: A() { cout << "1"; } ~A() { cout << "2"; }
};
class B : public A {
public: B() { cout << "3"; } ~B() { cout << "4"; }
};
int main() { B obj; }
👁️ إظهار الإجابة والتفسير
Answer: A) 1 3 4 2
Explanation:

Constructors: Base(1) -> Derived(3). Destructors: Derived(4) -> Base(2).

بالعامية: الأساس بيتبني الأول (A هيطبع 1)، بعدين الابن (B هيطبع 3). الهدد بيبقى العكس، نهدم الدور الأخير (B هيطبع 4)، وبعدين الأساس (A هيطبع 2). يبقى الناتج 1 3 4 2.

Q30. Implement Multiple Inheritance. Class 'Engine' and Class 'Wheels' are base classes. Class 'Car' inherits BOTH. Show how to initialize them in Car's constructor. Test in main().

Engine                 Wheels
-------                -------
- hp: int              - size: int
-------                -------
+ Engine(h: int)       + Wheels(s: int)
+ showHp()             + showSize()

          \           /
           \         /
            \       /
               Car (public Engine, public Wheels)
-------------------
- brand: string
-------------------
+ Car(h: int, s: int, b: string)
+ displayInfo(): void
👁️ إظهار الإجابة والتفسير
Answer:
#include 
#include 
using namespace std;

class Engine { // الأب الأول (المحرك)
protected:
    int hp; // قوة الحصان
public:
    Engine(int h) { hp = h; } // Constructor بتاع المحرك
    void showHp() { cout << "Engine HP: " << hp << endl; } // طباعة القوة
};

class Wheels { // الأب التاني (العجلات)
protected:
    int size; // مقاس العجلة
public:
    Wheels(int s) { size = s; } // Constructor بتاع العجل
    void showSize() { cout << "Wheel Size: " << size << " inches" << endl; } // طباعة المقاس
};

// Multiple Inheritance! Car inherits from BOTH Engine and Wheels
class Car : public Engine, public Wheels { // وراثة متعددة، العربية بتورثهم الاتنين
private:
    string brand; // ماركة العربية
public:
    // MUST call both base constructors in the initialization list!
    Car(int h, int s, string b) : Engine(h), Wheels(s) { // بندي الآباء القيم بتاعتهم هنا قبل أي حاجة
        brand = b; // بنخزن המاركة
    }
    
    void displayInfo() { // دالة بنجمع فيها الداتا
        cout << "Brand: " << brand << endl; // بنطبع الماركة
        showHp();   // الدالة دي جيالنا من الأب الأول (المحرك)
        showSize(); // الدالة دي جيالنا من الأب التاني (العجل)
    }
};

int main() {
    Car myCar(500, 19, "Ferrari"); // بنعمل عربية فيراري بقوة 500 وعجل 19
    myCar.displayInfo(); // بنعرض كل الداتا اللي اتجمعت من الوراثة
    return 0; // إنهاء
}

Explanation:

In Multiple Inheritance, the child has multiple parents. It must initialize all of them in its constructor's initializer list.

بالعامية: ده تطبيق على الوراثة المتعددة (Multiple Inheritance). العربية بتورث من محرك ومن عجلات. ففي Constructor بتاع العربية، لازم ننادي على Constructor الأب الأول والأب التاني في הـ Initialization List عشان يتملوا بيانات.

Q31. Implement Multi-level Inheritance. Base class 'Person', child 'Employee', grandchild 'Manager'. Chain the constructors correctly and test in main().

Person
-------------------
# name: string
-------------------
+ Person(n: string)
        ^
        |
    Employee
-------------------
# id: int
-------------------
+ Employee(n: string, i: int)
        ^
        |
    Manager
-------------------
- bonus: double
-------------------
+ Manager(n: string, i: int, b: double)
+ display(): void
👁️ إظهار الإجابة والتفسير
Answer:
#include 
#include 
using namespace std;

class Person { // الجد
protected:
    string name; // اسم الشخص
public:
    Person(string n) { name = n; } // الجد بياخد الاسم
};

class Employee : public Person { // الأب بيورث الجد
protected:
    int id; // رقم الموظف
public:
    // Pass 'n' up to Person
    Employee(string n, int i) : Person(n) { // بنسلم הـ name للجد في الأقواس بتاعت الـ Initialization
        id = i; // بنسجل הـ id
    }
};

class Manager : public Employee { // الابن بيورث الأب (كده بقى عندنا 3 مستويات)
private:
    double bonus; // البونص
public:
    // Pass 'n' and 'i' up to Employee
    Manager(string n, int i, double b) : Employee(n, i) { // بنسلم الداتا للأب
        bonus = b; // بنسجل الـ bonus
    }
    
    void display() {
        // Can access protected members from grandparents directly!
        cout << "Manager: " << name << ", ID: " << id << ", Bonus: $" << bonus << endl; // الـ name ده جاي من الجد مباشرة!
    }
};

int main() {
    Manager boss("Ahmed", 101, 5000.0); // عملنا المدير وبعتناله بيانات الـ 3 مستويات
    boss.display(); // طبعنا البيانات الموروثة
    return 0; // إنهاء
}

Explanation:

Constructor chaining is required in multi-level inheritance to pass arguments up the hierarchy.

بالعامية: الوراثة المتعددة المستويات (جد -> أب -> ابن). كل كلاس لازم يسلم المتغيرات للي فوقه في الـ Initialization List. ولأن المتغيرات `protected`، الحفيد قدر يستخدم `name` بتاع الجد مباشرة من غير Getter.

Q32. Design Hierarchical Inheritance. 'Vehicle' is base. 'Car' and 'Truck' both inherit from Vehicle. Demonstrate this structure in main() creating objects for both.

        Vehicle
       # speed: int
       + Vehicle(s)
          /    \
         /      \
     Car        Truck
- doors: int   - loadCapacity: int
+ Car(s, d)    + Truck(s, l)
+ show()       + show()
👁️ إظهار الإجابة والتفسير
Answer:
#include 
using namespace std;

class Vehicle { // الأب
protected:
    int speed; // السرعة (موروثة للأبناء)
public:
    Vehicle(int s) { speed = s; } // Constructor الأب
};

class Car : public Vehicle { // الابن الأول (عربية)
private:
    int doors; // الأبواب
public:
    Car(int s, int d) : Vehicle(s) { doors = d; } // بياخد السرعة يديها للأب
    void show() { cout << "Car Speed: " << speed << ", Doors: " << doors << endl; } // طباعة الداتا
};

class Truck : public Vehicle { // الابن التاني (شاحنة)
private:
    int loadCapacity; // الحمولة
public:
    Truck(int s, int l) : Vehicle(s) { loadCapacity = l; } // بياخد السرعة يديها للأب
    void show() { cout << "Truck Speed: " << speed << ", Load: " << loadCapacity << " Tons" << endl; } // طباعة الداتا
};

int main() {
    Car c(120, 4); // عملنا عربية
    Truck t(80, 10); // عملنا شاحنة
    
    c.show(); // طبعنا العربية اللي ورثت الـ speed من الأب
    t.show(); // طبعنا الشاحنة اللي كمان ورثت الـ speed من الأب
    
    return 0; // إنهاء
}

Explanation:

In hierarchical inheritance, multiple distinct child classes inherit from one single parent class.

بالعامية: الوراثة الهرمية، أب واحد (Vehicle) طالع منه كذا ابن (Car و Truck). كل ابن بيبعت الـ speed للأب عشان يتسجل عنده ويكمل بناء نفسه ببياناته الخاصة.

5. Polymorphism

📌 Virtual Functions, Early/Late Binding & Abstract Classes

Q33. What makes a class an 'Abstract Class' in C++?

👁️ إظهار الإجابة والتفسير
Answer: B) The class contains at least one pure virtual function (e.g. = 0)
Explanation:

A pure virtual function explicitly marks the class as a base-only concept, preventing instantiation.

بالعامية: عشان الكلاس يبقى Abstract ومحدش يقدر يعمل منه Object خالص، لازم يكون جواه دالة `virtual` ومكتوب جنبها `= 0` (Pure Virtual).

Q34. True or False?

A virtual destructor is important when you delete a derived object through a base class pointer.

👁️ إظهار الإجابة والتفسير
Answer: True
Explanation:

If the base destructor is not virtual, deleting via a base pointer will only call the base destructor, leaking derived class memory.

بالعامية: صح جداً ومهمة جداً. لو البوينتر نوعه (أب) وبيشاور على (ابن)، ولما تيجي تمسحه بـ delete لو الهدّام مش virtual، الكومبايلر هيمسح الأب بس ويسيب الابن يعمل Memory Leak!

Q35. What happens here and why?

class Base {
public: virtual void print() { cout << "Base"; }
};
class Derived : public Base {
public: void print() { cout << "Derived"; }
};
int main() {
    Base* ptr = new Derived();
    ptr->print();
}
👁️ إظهار الإجابة والتفسير
Answer: B) Prints 'Derived' because of Late Binding
Explanation:

The `virtual` keyword tells the compiler to check the actual object type at run-time (Late Binding), resolving to Derived.

بالعامية: بسبب كلمة `virtual` اللي في دالة الأب، الكومبايلر بيعمل Late Binding وبيستنى وقت التشغيل يشوف البوينتر بيشاور على أوبجيكت إيه بالظبط (بيشاور على Derived)، فبيطبع Derived.

Q36. Implement an Abstract Class 'Animal' with a pure virtual method 'sound()'. Create 'Dog' and 'Cat' derived classes. In main(), create an array of Animal pointers and loop through them to trigger Polymorphism.

Animal (Abstract)
-------------------
-------------------
+ virtual sound() = 0: void

        ^
   _____|_____
   |         |
  Dog       Cat
-------   -------
-------   -------
+ sound() + sound()
👁️ إظهار الإجابة والتفسير
Answer:
#include 
using namespace std;

// Abstract Class (عشان فيه Pure Virtual)
class Animal {
public:
    virtual void sound() = 0; // Pure Virtual Function (مفيش جسم للدالة)
    virtual ~Animal() {} // Virtual Destructor (أساسي عشان الـ Memory)
};

class Dog : public Animal { // الكلب بيورث من الحيوان
public:
    void sound() override { cout << "Dog says: Woof!\n"; } // لازم يطبق الدالة بتاعة الصوت
};

class Cat : public Animal { // القطة بتورث من الحيوان
public:
    void sound() override { cout << "Cat says: Meow!\n"; } // لازم تطبق الدالة بردو
};

int main() {
    // Array of Base Class Pointers (Polymorphism Magic!)
    Animal* zoo[2]; // مصفوفة بوينترات من نوع الأب
    zoo[0] = new Dog(); // الأول بيشاور على كلب
    zoo[1] = new Cat(); // التاني بيشاور على قطة
    
    cout << "--- Zoo Sounds ---\n";
    for(int i = 0; i < 2; i++) { // Loop للتشغيل
        // Late Binding happens here based on the actual object!
        zoo[i]->sound(); // الكومبايلر بيستنى وقت التشغيل وينادي الصوت الصح حسب الأوبجيكت الحقيقي!
    }
    
    // Cleanup
    for(int i = 0; i < 2; i++) { // بنلف عليهم نمسحهم
        delete zoo[i]; // بنمسحهم عشان الـ Memory Leak، وهنا الـ Virtual Destructor هيشتغل
    }
    
    return 0; // إنهاء
}

Explanation:

An array of base pointers iterating over derived objects is the classic, most powerful use-case of Polymorphism.

بالعامية: ده أعظم مثال يوضح الـ Polymorphism (تعدد الأوجه). عملنا مصفوفة بوينترات من نوع الأب Animal، وحطينا جواها كلب وقطة. ولما عملنا Loop نادينا دالة `sound()` واحدة بس، بس كل حيوان طلع الصوت بتاعه حسب نوعه الحقيقي (Late Binding).

Q37. Implement Function Overloading vs Overriding. Create a class MathBase with a virtual method 'compute(int)' and overloaded method 'compute(double)'. Inherit MathDerived and override 'compute(int)'. Test in main().

MathBase
-------------------
-------------------
+ virtual compute(x: int): void
+ compute(x: double): void

        ^
        |
   MathDerived
-------------------
-------------------
+ compute(x: int) override: void
👁️ إظهار الإجابة والتفسير
Answer:
#include 
using namespace std;

class MathBase { // الأب
public:
    // Virtual function ready for Overriding
    virtual void compute(int x) { // دالة بتاخد رقم صحيح
        cout << "Base compute(int): " << x * 2 << endl;
    }
    
    // Overloaded function (same name, different parameter)
    void compute(double x) { // نفس الاسم بس بتاخد كسر (ده اسمه Overloading جوه الكلاس)
        cout << "Base compute(double): " << x * 3.14 << endl;
    }
};

class MathDerived : public MathBase { // الابن
public:
    // Overriding the exact same signature
    void compute(int x) override { // كتبنا نفس الدالة بالظبط تاني عشان نعدلها (ده الـ Overriding مع الوراثة)
        cout << "Derived compute(int) overridden!: " << x * x << endl;
    }
    
    // Note: C++ hides overloaded base functions if a derived class overrides one of them
    // To unhide them, we use: using MathBase::compute;
    using MathBase::compute; // حيلة مهمة جداً عشان الدالة التانية بتاعة الكسر متستخباش
};

int main() {
    MathDerived obj; // عملنا الأوبجيكت من نوع الابن
    
    // Calls overridden Derived method
    obj.compute(5); // بينادي الدالة اللي تعدلت
    
    // Calls overloaded Base method (only works because of 'using' keyword)
    obj.compute(5.5); // بينادي دالة الكسر اللي جايالنا من الأب
    
    // Polymorphism test
    MathBase* ptr = &obj; // بوينتر من نوع الأب بيشاور عالابن
    ptr->compute(10); // Late binding -> calls Derived (بينادي الابن عشان virtual)
    
    return 0; // إنهاء
}

Explanation:

Demonstrates the subtle difference: Overloading is within the same scope with different parameters. Overriding is across inheritance scopes with the EXACT same parameters.

بالعامية: هنا بنشرح الفرق بين الـ Overloading (نفس الاسم بس بياخد داتا مختلفة جوه نفس الكلاس) والـ Overriding (الابن بيورث دالة من الأب وبيكتبها تاني بنفس كل حاجة عشان يعدلها). وفي הـ main جربنا الاتنين وجربنا הـ Polymorphism.