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

Lecture 9 & 10: Compile-time Polymorphism

المحاضرة 9 و 10: تعدد الأشكال المبكر (Compile-time Polymorphism)

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

Slide 3: الـ Compile-Time Polymorphism (الربط المبكر)

Slide 3

في المحاضرة اللي فاتت اتكلمنا عن الـ Run-Time Polymorphism (الـ Virtual Functions). النهاردة هنتكلم عن النوع التاني وهو Compile-Time Polymorphism.

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

النوع ده بيتحقق بطريقتين أساسيتين:

  1. Function Overloading (تعدد تحميل الدوال).
  2. Operator Overloading (تعدد تحميل المعاملات).

Slide 4: تحميل الدوال (Function Overloading)

Slide 4

الـ Function Overloading معناه إنك تعمل أكتر من دالة بنفس الاسم بالظبط جوه نفس الكلاس أو البرنامج.

طب إزاي الكومبايلر مش هيتلخبط؟ الكومبايلر بيفرق بينهم عن طريق الـ Signature (التوقيع)، واللي هو عبارة عن:

  • عدد المعاملات (Number of Parameters).
  • نوع المعاملات (Data Type of Parameters).
  • ترتيب المعاملات (Sequence of Parameters).
⚠️ ملاحظة هامة: الـ Return Type (زي int أو void) لا يُعتبر جزء من الـ Signature! يعني مينفعش تعمل دالتين بنفس الاسم ونفس الـ Parameters وتقولي أنا مغير الـ Return Type، الكومبايلر هيديك Error فوراً!

Slide 6: كود تحميل الدوال (Function Overloading Example)

Slide 6

تعالوا نشوف إزاي نستخدم نفس الدالة عشان نجمع أرقام صحيحة وأرقام عشرية:

class Maths { public: // Function 1: Adds two integers int sum(int a, int b) { return a + b; } // Function 2: Adds three integers (Different Number of Params) int sum(int a, int b, int c) { return a + b + c; } // Function 3: Adds two floats (Different Type of Params) float sum(float a, float b) { return a + b; } }; int main() { Maths obj; cout << obj.sum(10, 20); // Calls Function 1 cout << obj.sum(10, 20, 30); // Calls Function 2 cout << obj.sum(10.5f, 20.5f); // Calls Function 3 }

Slide 9: تحميل المعاملات (Operator Overloading)

Slide 9

ميزة عبقرية في الـ C++ هي الـ Operator Overloading.

لو عندك متغيرين عاديين (int x, y;)، تقدر تجمعهم بعلامة الزائد x + y. بس لو عندك كائنين (Objects) من كلاس إنت عامله (زي كلاس ComplexNumber)، الكومبايلر ميعرفش إزاي يجمعهم لو كتبت obj1 + obj2 وهيديك Error.

هنا بييجي دورك إنك تدي معنى جديد لعظمة الـ + (أو أي Operator تاني) عشان الكومبايلر يفهم إزاي يجمع الـ Objects دي مع بعض.

Slide 10: قواعد تحميل المعاملات (Rules of Operator Overloading)

Slide 10

العملية دي مش سايبة، ليها قواعد صارمة جداً بتيجي دايماً كـ True/False في الامتحانات:

  • 1. معاني أساسية: متقدرش تغير الطريقة اللي الـ Operator بيشتغل بيها مع الـ Built-in types (يعني متقدرش تخلي الـ + يطرح الأرقام الصحيحة العادية).
  • 2. قواعد الـ Syntax: متقدرش تغير أولوية المعاملات (Precedence) ولا اتجاهها (Associativity). الضرب هيفضل يتنفذ قبل الجمع.
  • 3. المعاملات الممنوعة: فيه 4 معاملات مستحيل تعامل معاهم Overloading:
    . (Dot operator)
    :: (Scope resolution)
    ?: (Ternary conditional)
    sizeof

Slide 12: تحميل المعاملات الأحادية (Unary Operator Overloading)

Slide 12

الـ Unary Operators هي المعاملات اللي بتشتغل على متغير واحد بس (زي ++ أو -- أو - اللي بتعكس الإشارة).

لما بنيجي نعملها Overloading جوه الكلاس، الدالة مبتاخدش أي Parameters (أقواسها فاضية)، لأنها بتشتغل على الـ Object اللي نادى عليها مباشرة عن طريق الـ this pointer.

class Counter { private: int count; public: Counter() { count = 0; } // Overloading the prefix ++ operator (Syntax: returnType operator OP ()) void operator ++ () { count = count + 1; } }; int main() { Counter c1; ++c1; // This implicitly calls c1.operator++() }

Slide 15: تحميل المعاملات الثنائية (Binary Operator Overloading)

Slide 15

الـ Binary Operators هي المعاملات اللي محتاجة طرفين (يمين وشمال) عشان تشتغل (زي + و - و * و <).

هنا القاعدة مختلفة: لما نكتب obj1 + obj2، اللي بيحصل إن الكائن اللي على الشمال (obj1) هو اللي بينادي الدالة، وبياخد الكائن اللي على اليمين (obj2) كـ Parameter!

عشان كده دالة الـ Binary Overloading دايماً بتاخد One Parameter فقط (الطرف اليمين).

class Complex { private: int real, imag; public: Complex(int r=0, int i=0) { real = r; imag = i; } // Binary Overloading for + // Returns a new Complex object. Takes right side as parameter. Complex operator + (const Complex &obj2) { Complex temp; // 'real' is from the calling object (left side) // 'obj2.real' is from the parameter (right side) temp.real = real + obj2.real; temp.imag = imag + obj2.imag; return temp; } }; int main() { Complex c1(10, 5), c2(2, 4); Complex c3; // Compiler translates this to: c3 = c1.operator+(c2); c3 = c1 + c2; }

Quiz 1: Overloading Mechanics

1. Which of the following C++ operators CANNOT be overloaded under any circumstances?

2. When overloading a Binary Operator (like `+`) as a standard member function of a class, how many parameters should the function take?

Slide 23: القوالب (Templates - Generic Programming)

Slide 23

في الـ Function Overloading، لو عايز دالة تجمع أرقام صحيحة، بتكتب كود، ولو عايز نفس الدالة تجمع أرقام عشرية، بتضطر تكرر نفس الكود بالظبط بس تغير الـ Data Type من int لـ float!

دي حاجة مرهقة جداً وبتخالف مبدأ الـ OOP في عدم التكرار. الحل العبقري هو الـ Templates (القوالب)، أو ما يسمى بـ Generic Programming (البرمجة العامة).

الـ Template بيخليك تكتب الدالة أو الكلاس مرة واحدة بس، وتسيب الـ Data Type مجهول (Generic). والكومبايلر هو اللي هيستنتج النوع المناسب وقت التشغيل!

Slide 24: قوالب الدوال (Function Templates)

Slide 24

عشان نحول أي دالة عادية لـ Template، بنكتب قبلها سطر تعويذة: template <typename T> أو template <class T>.

حرف الـ T ده بيمثل الـ Data Type المجهول. (ممكن تسميه أي اسم، بس T هو العرف السائد).

// One function to rule them all! template <typename T> T get_max(T x, T y) { if (x > y) return x; else return y; } int main() { // Compiler creates an 'int' version automatically cout << get_max<int>(3, 7) << endl; // Compiler creates a 'double' version automatically cout << get_max<double>(3.5, 1.2) << endl; // Compiler creates a 'char' version automatically cout << get_max<char>('g', 'e') << endl; }
💡 ملحوظة: في أحدث نسخ الـ C++، إنت مش مضطر تكتب الـ Type بين أقواس الزاوية <int> وإنت بتنادي الدالة، الكومبايلر بيقدر يستنتجه لوحده من نوع الأرقام اللي إنت باعتها!

Slide 27: قوالب الكلاسات (Class Templates)

Slide 27

نفس فكرة الـ Function Templates بتطبق على الكلاسات بالكامل! لو عندك كلاس بيخزن بيانات (زي كلاس Box)، وإنت عايز اليوزر يحدد هل الـ Box ده هيشيل int ولا string ولا double؟

template <class T> class Box { private: T data; // Variable of generic type T public: Box(T d) { data = d; } T get_data() { return data; } }; int main() { // For Class Templates, you MUST specify the type in angle brackets! Box<int> intBox(123); cout << intBox.get_data() << endl; Box<string> strBox("Hello Templates!"); cout << strBox.get_data() << endl; }

Final Quiz: Templates

1. What is the main purpose of using Templates in C++?

2. Which of the following is the correct syntax to instantiate an object of a Class Template named `Stack` to hold integers?

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

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

Question: Explain Function Overloading and Operator Overloading as forms of Compile-Time Polymorphism. List the operators that cannot be overloaded. Then explain Templates (Function and Class) and how they achieve Generic Programming.

🖥️ What is the output of the following code?

Q1:

void print(int a) { cout << "Integer: " << a << endl; } void print(double a) { cout << "Double: " << a << endl; } int main() { print(5); print(3.14); }

Q2:

template <typename T> T add(T a, T b) { return a + b; } int main() { cout << add<int>(10, 20) << " "; cout << add<string>("A", "B") << endl; }

✍️ Write a line of code for the following statements

Q1: Write the signature of an overloaded + operator as a member function of class Complex that adds two Complex objects.

Q2: Write the signature of an overloaded prefix ++ operator as a member function of class Counter.

Q3: Write the signature of a generic Function Template called findMax that returns the larger of two values of type T.

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

class Point { private: int x, y; public: Point(int x=0, int y=0) { this->x = x; this->y = y; } Point operator+(Point p2) { Point temp; temp.x = x + p2.x; temp.y = y + p2.y; return temp; } void print() { cout << x << "," << y << endl; } }; int main() { Point p1(1, 2), p2(3, 4); Point p3 = p1 + p2; p3.print(); }

a) What is the output?

b) In the expression p1 + p2, which object is implicitly passed and which is explicitly passed as a parameter?

c) Can we overload the sizeof operator in C++?