تعد الوراثة المتعددة في C ++ قوية ، ولكنها أداة صعبة ، وغالبًا ما تؤدي إلى مشاكل إذا لم يتم استخدامها بعناية — مشاكل مثل مشكلة الماس.
في هذه المقالة ، سنناقش مشكلة الماس ، وكيف تنشأ من تعدد الميراث ، وما يمكنك القيام به لحل المشكلة.
الوراثة المتعددة في C ++
تعد الميراث أ ميزة البرمجة الشيئية (OOP) حيث يمكن للفئة الفرعية أن ترث من أكثر من فئة عليا واحدة. بمعنى آخر ، يمكن أن يكون للفصل الفرعي أكثر من والد واحد.
يوضح الشكل أدناه تمثيلًا تصويريًا للإرث المتعدد.
في الرسم البياني أعلاه ، فئة ج لديها فئة أ و الصف ب كأبوين لها.
إذا أخذنا في الاعتبار سيناريو من واقع الحياة ، يرث الطفل من أبيه وأمه. لذلك يمكن تمثيل الطفل كفئة مشتقة مع "الأب" و "الأم" كأبوين له. وبالمثل ، يمكن أن يكون لدينا العديد من الأمثلة الواقعية على الميراث المتعدد.
في الوراثة المتعددة ، يتم تنفيذ منشئي الفئة الموروثة بالترتيب الموروث. من ناحية أخرى ، يتم تنفيذ المدمرات بالترتيب العكسي لميراثهم.
الآن دعنا نوضح الوراثة المتعددة ونتحقق من ترتيب البناء وتدمير الأشياء.
رمز توضيحي لتعدد الميراث
بالنسبة للتوضيح الوراثي المتعدد ، قمنا ببرمجة التمثيل أعلاه بالضبط في C ++. يتم إعطاء رمز البرنامج أدناه.
#يشمل
استخدام اسم للمحطة؛
الفئة A // الفئة الأساسية A مع المُنشئ والمُدمِّر
{
عام:
أ () {cout << "class A:: Constructor" << endl؛ }
~ A () {cout << "class A:: Destructor" << endl؛ }
};
الفئة B // الفئة الأساسية B مع المُنشئ والمُدمِّر
{
عام:
B () {cout << "class B:: Constructor" << endl؛ }
~ B () {cout << "class B:: Destructor" << endl؛ }
};
الفئة C: عامة B ، عامة A // فئة مشتقة C ترث الفئة A ثم الفئة B (لاحظ الترتيب)
{
عام:
C () {cout << "class C:: Constructor" << endl؛ }
~ C () {cout << "class C:: Destructor" << endl؛ }
};
انت مين(){
نسخة؛
العودة 0 ؛
}
الإخراج الذي نحصل عليه من البرنامج أعلاه هو كما يلي:
فئة ب:: منشئ
فئة أ:: منشئ
فئة C:: منشئ
صنف C:: مدمر
فئة أ:: مدمر
صنف ب:: مدمر
الآن إذا تحققنا من المخرجات ، فسنلاحظ أنه يتم استدعاء المنشئات بالترتيب B و A و C بينما تكون المدمرات بترتيب عكسي. الآن بعد أن عرفنا أساسيات الميراث المتعدد ، ننتقل إلى مناقشة مشكلة الماس.
شرح مشكلة الماس
تحدث مشكلة الماس عندما يرث فصل دراسي من صنفين من الأبوين يشتركان في فئة الأجداد المشتركة. وهذا موضح في الرسم البياني أدناه:
هنا ، لدينا فصل طفل وراثة من الطبقات أب و الأم. هاتان الفئتان ، بدورهما ، ترثان الفصل شخص لأن كلا من الأب والأم شخص.
كما هو مبين في الشكل ، يرث "طفل الصف" صفات "الشخص" مرتين - مرة من الأب ومرة أخرى من الأم. هذا يثير الغموض لأن المترجم يفشل في فهم الطريق الذي يجب أن يسلكه.
يؤدي هذا السيناريو إلى ظهور رسم بياني للميراث على شكل ماسة ويُعرف باسم "مشكلة الألماس".
رسم توضيحي لمشكلة الماس
أدناه قمنا بتمثيل المثال أعلاه للميراث على شكل الماس برمجيًا. وفيما يلي التعليمات البرمجية:
#يشمل
استخدام اسم للمحطة؛
فئة الشخص {// فئة الشخص
عام:
شخص (int x) {cout << "شخص:: شخص (int) يُدعى" << endl؛ }
};
فئة الأب: شخص عام {// فئة الأب يرث الشخص
عام:
الأب (int x): الشخص (x) {
cout << "الأب:: الأب (int) المسمى" << endl؛
}
};
فئة الأم: شخص عام {// فئة الأم ترث شخصًا
عام:
الأم (int x): الشخص (x) {
cout << "Mother:: Mother (int) تسمى" << endl؛
}
};
فئة الطفل: أب عام ، أم عام {// الأب يرث الأب والأم
عام:
الطفل (int x): الأم (x) ، الأب (x) {
cout << "Child:: Child (int) يسمى" << endl؛
}
};
انت مين() {
طفل طفل (30) ؛
}
فيما يلي مخرجات هذا البرنامج:
الشخص:: تم استدعاء الشخص (int)
الأب:: الأب (int) دعا
الشخص:: تم استدعاء الشخص (int)
الأم:: اسم الأم (int)
طفل:: طفل (int) يسمى
الآن يمكنك رؤية الغموض هنا. يتم استدعاء مُنشئ فئة الشخص مرتين: مرة عند إنشاء كائن فئة الأب والتالي عند إنشاء كائن الفئة الأم. يتم توريث خصائص فئة الشخص مرتين ، مما يؤدي إلى الغموض.
نظرًا لأنه يتم استدعاء مُنشئ فئة الشخص مرتين ، فسيتم أيضًا استدعاء المدمر مرتين عندما يتم إتلاف كائن الفئة التابعة.
الآن إذا فهمت المشكلة بشكل صحيح ، فلنناقش حل مشكلة الماس.
كيفية إصلاح مشكلة الماس في C ++
حل مشكلة الماس هو استخدام افتراضية كلمة رئيسية. نصنع فئتي الوالدين (اللتين ترثان من نفس فئة الأجداد) في فصول افتراضية من أجل تجنب نسختين من فئة الأجداد في فصل الأطفال.
دعنا نغير الرسم التوضيحي أعلاه ونتحقق من الإخراج:
رمز توضيح لإصلاح مشكلة الماس
#يشمل
استخدام اسم للمحطة؛
فئة الشخص {// فئة الشخص
عام:
شخص () {cout << "Person:: Person () يُدعى" << endl؛ } // المنشئ الأساسي
شخص (int x) {cout << "شخص:: شخص (int) يُدعى" << endl؛ }
};
فئة الأب: شخص عام افتراضي {// فئة الأب يرث الشخص
عام:
الأب (int x): الشخص (x) {
cout << "الأب:: الأب (int) المسمى" << endl؛
}
};
فئة الأم: شخص عام افتراضي {// فئة الأم ترث شخصًا
عام:
الأم (int x): الشخص (x) {
cout << "Mother:: Mother (int) تسمى" << endl؛
}
};
فئة الطفل: أب عام ، أم عام {// فئة الطفل يرث الأب والأم
عام:
الطفل (int x): الأم (x) ، الأب (x) {
cout << "Child:: Child (int) يسمى" << endl؛
}
};
انت مين() {
طفل طفل (30) ؛
}
هنا استخدمنا ملف افتراضية الكلمة الأساسية عندما يرث الأب والأم فئة الشخص. يُطلق على هذا عادةً اسم "الوراثة الافتراضية" ، والذي يضمن تمرير مثيل واحد فقط من الفئة الموروثة (في هذه الحالة ، فئة الشخص).
بمعنى آخر ، سيكون لفصل الطفل مثيل واحد لفئة الشخص ، يتشاركها كل من فئتي الأب والأم. من خلال وجود مثيل واحد لفئة الشخص ، يتم حل الغموض.
ناتج الكود أعلاه معطى أدناه:
الشخص:: شخص () تم استدعاؤه
الأب:: الأب (int) دعا
الأم:: اسم الأم (int)
طفل:: طفل (int) يسمى
هنا يمكنك أن ترى أنه تم استدعاء مُنشئ Class Person مرة واحدة فقط.
شيء واحد يجب ملاحظته حول الوراثة الافتراضية هو أنه حتى لو كان المُنشئ ذو المعلمات لـ يتم استدعاء فئة الشخص بشكل صريح بواسطة منشئي فئة الأب والأم من خلال التهيئة القوائم ، سيتم استدعاء المنشئ الأساسي لفئة الشخص فقط.
هذا بسبب وجود مثيل واحد فقط من فئة أساسية افتراضية يتم مشاركتها بواسطة فئات متعددة ترث منها.
لمنع المُنشئ الأساسي من التشغيل عدة مرات ، لا يتم استدعاء المُنشئ لفئة أساسية افتراضية بواسطة الفئة الموروثة منها. بدلاً من ذلك ، يتم استدعاء المُنشئ من قبل مُنشئ الطبقة الخرسانية.
في المثال أعلاه ، يستدعي الفصل Child مباشرة المُنشئ الأساسي للفئة Person.
متعلق ب: دليل المبتدئين لمكتبة القوالب القياسية في C ++
ماذا لو احتجت إلى تنفيذ المُنشئ ذي المعلمات للفئة الأساسية؟ يمكنك القيام بذلك عن طريق الاتصال به صراحةً في فصل الطفل بدلاً من فصول الأب أو الأم.
حل مشكلة الماس في لغة ++ C
مشكلة الألماس هي غموض ينشأ في تعدد الميراث عندما ترث فئتان من الأبوين من نفس فئة الأجداد ، وكلا الفئتين الأبوين موروثة من قبل صف واحد من الأبناء. بدون استخدام الوراثة الافتراضية ، ترث فئة الأطفال خصائص فئة الأجداد مرتين ، مما يؤدي إلى الغموض.
يمكن أن يظهر هذا بشكل متكرر في رمز العالم الحقيقي ، لذلك من المهم معالجة هذا الغموض متى تم رصده.
تم إصلاح مشكلة الماس باستخدام الوراثة الافتراضية ، حيث يتم حل افتراضية يتم استخدام الكلمة الأساسية عندما ترث فصول الوالدين من فئة الأجداد المشتركة. من خلال القيام بذلك ، يتم عمل نسخة واحدة فقط من فئة الأجداد ، ويتم إنشاء كائن فئة الأجداد بواسطة فئة الأطفال.
هل تريد تعلم البرمجة ولكن لا تعرف من أين تبدأ؟ ستبدأ مشاريع البرمجة والبرامج التعليمية هذه للمبتدئين.
اقرأ التالي
- برمجة
- البرمجة C
اشترك في نشرتنا الإخبارية
انضم إلى النشرة الإخبارية لدينا للحصول على نصائح تقنية ومراجعات وكتب إلكترونية مجانية وصفقات حصرية!
انقر هنا للاشتراك