إذا كانت الفئات (Classes) هي قلب البرمجة الكينونية، فـ الوراثة (Inheritance) هي الدم اللي يجري فيها.
هي الجسر اللي بيخليك تنتقل من “برمجة متفرقة” إلى “تصميم منطقي منظم”، من كتابة كود مكرر إلى كتابة كود ذكي يُعاد استخدامه بدون عناء.
في هذا الدرس الطويل، رح نفكك مفهوم الوراثة من جذوره، من الفكر اللي وراءه إلى التطبيق العملي في C++.
رح تعرف مش بس “كيف تكتب كود وراثة”، بل “لماذا تحتاج الوراثة”، “كيف تفكر فيها”، و”متى تتجنبها أصلاً”.
🧠 ما هي الوراثة (Inheritance)؟
في الحياة الواقعية، الابن يرث من والده: الشكل، الجينات، بعض الصفات، وربما المهنة.
في البرمجة الكينونية، نفس الشيء:
الفئة الابنة (Derived Class) ترث من الفئة الأم (Base Class) الخصائص والدوال، وتقدر تستخدمها أو تعدلها أو توسّعها.
باختصار:
الوراثة هي إعادة استخدام الكود + التوسعة عليه بطريقة منطقية وآمنة.
⚙️ الفكرة الجوهرية
الوراثة تسمح لك تبني نظام يعتمد على العلاقات الطبيعية بين الكائنات.
مثلاً:
- عندك فئة عامة اسمها
Personتحتوي على خصائص مشتركة: الاسم، العمر، الوظيفة. - بعدها تنشئ فئة
Studentترث منPersonوتضيف لها خصائصها الخاصة: التخصص، رقم الطالب. - ثم فئة
Teacherترث منPersonوتضيف خصائص مثل الراتب، القسم.
بهذا الشكل، وفّرت كود، نظّمت المنطق، وخليت العلاقة بين الكائنات واضحة وبشرية أكثر.
🧩 التركيب العام للوراثة في C++
class BaseClass {
// خصائص ودوال الفئة الأم
};
class DerivedClass : access_modifier BaseClass {
// خصائص ودوال الفئة الابنة
};
BaseClass→ الفئة الأم.DerivedClass→ الفئة الابنة.access_modifier→ طريقة الوراثة (public / private / protected).
🎯 هدف الوراثة باختصار
- إعادة استخدام الكود (Code Reusability).
- تحسين التصميم الهيكلي للكود.
- إنشاء تسلسل منطقي بين الكائنات (Hierarchy).
- تقليل الأخطاء الناتجة عن التكرار.
- تسهيل الصيانة والتطوير.
🔹 أبسط مثال ممكن
#include <iostream>
using namespace std;
class Person {
public:
string name;
int age;
void introduce() {
cout << "مرحباً، أنا " << name << " وعمري " << age << " سنة." << endl;
}
};
class Student : public Person {
public:
string major;
void study() {
cout << name << " يدرس تخصص " << major << "." << endl;
}
};
int main() {
Student s1;
s1.name = "محمد";
s1.age = 20;
s1.major = "برمجة";
s1.introduce();
s1.study();
}
📤 النتيجة:
مرحباً، أنا محمد وعمري 20 سنة.
محمد يدرس تخصص برمجة.
لاحظ:
- لم نعرّف
nameوageداخلStudent، لكنها أصبحت متوفرة بفضل الوراثة. - الطالب الآن ورث صفات الإنسان، وأضاف صفاته الخاصة.
🔍 أنواع الوراثة في C++
C++ تدعم عدة أنواع من الوراثة — بعضها بسيط وواضح، وبعضها متقدم جدًا وموجود لخدمة سيناريوهات معينة في الأنظمة الكبيرة.
| النوع | الوصف | مثال واقعي |
|---|---|---|
| الوراثة الأحادية (Single) | فئة واحدة ترث من فئة واحدة | Student من Person |
| الوراثة المتعددة (Multiple) | فئة ترث من أكثر من فئة | SmartPhone من Camera و Phone |
| الوراثة المتسلسلة (Multilevel) | فئة ترث من فئة ترث من فئة | GrandChild → Child → Parent |
| الوراثة الهرمية (Hierarchical) | عدة فئات ترث من فئة واحدة | Teacher, Student ← Person |
| الوراثة الهجينة (Hybrid) | مزيج من أكثر من نوع | Employee يرث من Person و Worker |
🧱 1. الوراثة الأحادية (Single Inheritance)
هي النوع الأكثر شيوعًا. فئة واحدة ترث من فئة واحدة فقط.
class Vehicle {
public:
void move() {
cout << "المركبة تتحرك..." << endl;
}
};
class Car : public Vehicle {
public:
void horn() {
cout << "السيارة تطلق البوق!" << endl;
}
};
int main() {
Car c;
c.move(); // موروثة من Vehicle
c.horn(); // من Car نفسها
}
📤 النتيجة:
المركبة تتحرك...
السيارة تطلق البوق!
🧩 2. الوراثة المتعددة (Multiple Inheritance)
الفئة الجديدة ترث من أكثر من فئة أم.
class Engine {
public:
void start() {
cout << "تم تشغيل المحرك!" << endl;
}
};
class Radio {
public:
void play() {
cout << "تشغيل الموسيقى..." << endl;
}
};
class Car : public Engine, public Radio {
public:
void drive() {
cout << "السيارة تتحرك!" << endl;
}
};
📤 النتيجة:
تم تشغيل المحرك!
تشغيل الموسيقى...
السيارة تتحرك!
لكن انتبه ⚠️
الوراثة المتعددة قوية… لكنها سلاح ذو حدّين.
لو استخدمتها بدون تنظيم ممكن تدخل في تعارض أسماء ودوال (الـ Diamond Problem المشهور — راح نوصله بعد شوي).
🧩 3. الوراثة المتسلسلة (Multilevel Inheritance)
فئة ترث من فئة أخرى، وهذه بدورها ترث من فئة ثالثة.
class LivingBeing {
public:
void breathe() { cout << "يتنفس..." << endl; }
};
class Animal : public LivingBeing {
public:
void eat() { cout << "يأكل..." << endl; }
};
class Dog : public Animal {
public:
void bark() { cout << "ينبح!" << endl; }
};
int main() {
Dog d;
d.breathe(); // من LivingBeing
d.eat(); // من Animal
d.bark(); // من Dog
}
📤 النتيجة:
يتنفس...
يأكل...
ينبح!
🔹 الفكرة واضحة: كل مستوى يرث كل ما قبله.
🧩 4. الوراثة الهرمية (Hierarchical Inheritance)
عدة فئات ترث من فئة أم واحدة.
class Person {
public:
void speak() { cout << "يتحدث..." << endl; }
};
class Teacher : public Person {
public:
void teach() { cout << "المعلم يشرح الدرس." << endl; }
};
class Student : public Person {
public:
void study() { cout << "الطالب يذاكر." << endl; }
};
كل من Teacher و Student يرث نفس الخصائص من Person.
🧩 5. الوراثة الهجينة (Hybrid Inheritance)
دمج أكثر من نوع وراثة.
وغالبًا تُستخدم في أنظمة كبيرة جدًا مثل أنظمة التشغيل أو محركات الألعاب.
لكنها خطيرة لأنها تسبب “الوراثة الماسية” (Diamond Inheritance Problem).
💎 مشكلة الوراثة الماسية (Diamond Problem)
تحدث عندما ترث فئة من فئتين، كلاهما يرث من نفس الفئة الأم.
class A {
public:
void greet() { cout << "مرحباً من A" << endl; }
};
class B : public A {};
class C : public A {};
class D : public B, public C {};
int main() {
D obj;
// obj.greet(); ❌ غموض: من أي نسخة من A؟
obj.B::greet(); // ✅
}
💡 الحل في C++ هو الوراثة الافتراضية (Virtual Inheritance)
(رح نخصص لها درس خاص لاحقًا لأنها موضوع متقدّم جدًا.)
⚙️ مستويات الوصول في الوراثة (Access Control in Inheritance)
واحدة من أكثر النقاط اللي بتلخبط المبتدئين.
الفئة الأم ممكن تحتوي على عناصر:
publicprotectedprivate
ونوع الوراثة نفسه (public/protected/private) بيحدد كيف تنتقل هذه العناصر إلى الفئة الابنة.
| نوع العنصر في الفئة الأم | عند الوراثة بـ public | عند الوراثة بـ protected | عند الوراثة بـ private |
|---|---|---|---|
public | يبقى public | يصبح protected | يصبح private |
protected | يبقى protected | يبقى protected | يصبح private |
private | لا يُورث | لا يُورث | لا يُورث |
📘 مثال عملي:
class Base {
public:
int a;
protected:
int b;
private:
int c;
};
class Derived : public Base {
public:
void show() {
a = 1; // ✅
b = 2; // ✅
// c = 3; ❌ لا يمكن الوصول إليه
}
};
🧠 استخدام الـ protected
protected يعني:
- لا يمكن الوصول له من خارج الفئة.
- لكن يمكن للفئات الموروثة استخدامه.
class Human {
protected:
string name;
};
class Student : public Human {
public:
void setName(string n) {
name = n; // ✅ مسموح لأنها موروثة ومحميّة
}
void introduce() {
cout << "اسمي " << name << endl;
}
};
🔄 الـ Constructor & Destructor مع الوراثة
الفئات الموروثة تستدعي منشئات ومدمّرات الفئات الأساسية تلقائيًا.
📘 مثال:
#include <iostream>
using namespace std;
class Base {
public:
Base() { cout << "Constructor من Base\n"; }
~Base() { cout << "Destructor من Base\n"; }
};
class Derived : public Base {
public:
Derived() { cout << "Constructor من Derived\n"; }
~Derived() { cout << "Destructor من Derived\n"; }
};
int main() {
Derived d;
}
📤 النتيجة:
Constructor من Base
Constructor من Derived
Destructor من Derived
Destructor من Base
لاحظ الترتيب:
- المنشئات من الأعلى للأسفل.
- المدمرات بالعكس (من الأسفل للأعلى).
🧩 تعديل الدوال الموروثة (Overriding)
الفئة الابنة ممكن تعيد تعريف (override) دوال الفئة الأم بنفس الاسم.
class Animal {
public:
void sound() { cout << "صوت الحيوان..." << endl; }
};
class Dog : public Animal {
public:
void sound() { cout << "ينبح!" << endl; }
};
لكن لو بدك تتعامل مع الدوال الموروثة بطريقة ذكية (runtime polymorphism) لازم تستخدم الكلمة virtual — وهذا موضوع درس قادم مخصص بالكامل (الدوال الافتراضية).
🧱 مثال تطبيقي شامل يجمع المفاهيم
#include <iostream>
using namespace std;
class Person {
public:
string name;
int age;
Person(string n, int a) : name(n), age(a) {}
void introduce() {
cout << "أنا " << name << "، عمري " << age << " سنة.\n";
}
};
class Employee : public Person {
public:
int salary;
Employee(string n, int a, int s) : Person(n, a) {
salary = s;
}
void work() {
cout << name << " يعمل ويتقاضى " << salary << " دولاراً.\n";
}
};
class Manager : public Employee {
public:
string department;
Manager(string n, int a, int s, string d)
: Employee(n, a, s), department(d) {}
void lead() {
cout << "المدير " << name << " يقود قسم " << department << ".\n";
}
};
int main() {
Manager m("محمد", 30, 5000, "البرمجة");
m.introduce();
m.work();
m.lead();
}
📤 النتيجة:
أنا محمد، عمري 30 سنة.
محمد يعمل ويتقاضى 5000 دولاراً.
المدير محمد يقود قسم البرمجة.
🧰 متى تستخدم الوراثة؟ ومتى لا تستخدمها؟
✅ استخدم الوراثة عندما:
- يوجد علاقة من نوع “is-a” بين الفئات.
مثل:Student is a Person,Car is a Vehicle. - تريد إعادة استخدام كود موجود دون تكراره.
- عندك خصائص مشتركة بين عدة كائنات.
❌ لا تستخدم الوراثة عندما:
- العلاقة ليست من نوع “is-a” (مثلاً:
Engineليس نوع منCarبل جزء منها). - يؤدي استخدامها إلى تعقيد غير ضروري في الشيفرة.
- يمكن تحقيق المطلوب باستخدام التجميع (Composition) بدلاً منها.
📚 الفرق بين الوراثة (Inheritance) والتجميع (Composition)
| المقارنة | Inheritance | Composition |
|---|---|---|
| العلاقة | “is-a” | “has-a” |
| مثال | Car is a Vehicle | Car has an Engine |
| المرونة | أقل | أعلى |
| وقت التغيير | صعب التعديل | أسهل |
🌍 روابط خارجية موثوقة
- 🔗 cppreference – Derived classes
- 🔗 GeeksForGeeks – Inheritance in C++
- 🔗 Programiz – C++ Inheritance Guide
- 🔗 W3Schools – C++ Inheritance
🧩 الخلاصة النهائية
الوراثة في C++ مش مجرد طريقة لتقليل كتابة الكود، هي فلسفة كاملة في التفكير.
- تبني نظام منطقي بين الكائنات.
- تسهّل التطوير والصيانة.
- تحافظ على “العلاقات” كما في الحياة الواقعية.
- تفتح الباب أمام مفاهيم أعمق مثل:
- التعددية (Polymorphism)
- الدوال الافتراضية (Virtual Functions)
- الوراثة الافتراضية (Virtual Inheritance)
- التحويلات بين الكائنات (Upcasting & Downcasting)
كلها مفاهيم رح نفهمها واحدة وراء الثانية.
🧭 كلمة أخيرة بأسلوب كود التطور
الوراثة هي فن إعادة استخدام الذكاء.
ما تكتب كود جديد… لو في كود قديم يمكن تعلّمه “شيء جديد”.
خلي الكائنات عندك تتكلم، تفكر، وتتعلم من بعض — وقتها بتصير فعلاً مبرمج كائني التفكير، مش بس كائني الكود.
اكتشاف المزيد من كود التطور
اشترك للحصول على أحدث التدوينات المرسلة إلى بريدك الإلكتروني.


