c++ تعليق - هل الكلمة الرئيسية "تجاوز" مجرد تحقق لطريقة افتراضية تم تجاوزها؟




عربي ستار (5)

بقدر ما أفهم ، فإن إدخال كلمة رئيسية في C ++ 11 لا يعدو كونه أكثر من مجرد فحص للتأكد من أن الوظيفة التي يتم تنفيذها هي override الدالة virtual في الفئة الأساسية.

هل هاذا هو؟


Answers

يعتبر " التجاوز " مفيدًا عندما يقوم أحدهم بتجديد طريقة افتراضية لطبقة أساسية محدثة مثل إضافة معلمة اختيارية ولكنه نسي تحديث توقيع أسلوب الفئة المشتقة. في هذه الحالة ، لم تعد الطرق بين القاعدة والفئة المشتقة علاقة متعددة الأشكال. بدون بيان الإلغاء ، من الصعب معرفة هذا النوع من الأخطاء.



هذا في الواقع الفكرة. النقطة هي أنك صريح حول ما تعنيه ، بحيث يمكن تشخيص خطأ صامت خلاف ذلك:

struct Base
{
    virtual int foo() const;
};

struct Derived : Base
{
    virtual int foo()   // whoops!
    {
       // ...
    }
};

التعليمات البرمجية أعلاه برمجيًا ، ولكن ليس ما قد تعنيه (لاحظ const ). إذا قلت بدلاً من ذلك ، virtual int foo() override ، عندئذ ستحصل على خطأ مترجم بأن وظيفتك لا تكتفي في الواقع virtual int foo() override أي شيء.


ويكيبيديا اقتباس:

يعني المعرف الخاص override أن المحول البرمجي سيتحقق من class (es) الأساسي لمعرفة ما إذا كانت هناك دالة ظاهرية بهذا التوقيع بالضبط. وإذا لم يكن هناك ، فسيخفق المترجم.

http://en.wikipedia.org/wiki/C%2B%2B11#Explicit_overrides_and_final

تحرير (محاولة تحسين الإجابة قليلاً):

الإعلان عن طريقة "تجاوز" يعني أن هذه الطريقة تهدف إلى إعادة كتابة طريقة (افتراضية) على الطبقة الأساسية. يجب أن يكون لطريقة overriding نفس التوقيع (على الأقل بالنسبة لمعلمات الإدخال) كطريقة تعتزم إعادة الكتابة.

لماذا هذا ضروري؟ حسنًا ، يتم منع حالتين الخطأ الشائعة التالية:

  1. واحد mistypes نوع في الطريقة الجديدة. المترجم ، غير مدركين أنه ينوي كتابة أسلوب سابق ، ببساطة يضيفه إلى الفصل كطريقة جديدة. المشكلة هي أن الأسلوب القديم لا يزال هناك ، يتم إضافة واحدة جديدة كحمل زائد. في هذه الحالة ، ستعمل جميع المكالمات باتجاه الأسلوب القديم كما كانت من قبل ، دون أي تغيير في السلوك (وهو ما كان الغرض من إعادة الكتابة).

  2. ينسى المرء أن يعلن عن الأسلوب في الطبقة الفائقة بأنه "ظاهري" ، لكنه لا يزال يحاول إعادة كتابته في فئة فرعية. في حين أن هذا سوف يتم قبوله على ما يبدو ، فإن السلوك لن يكون على النحو المنشود بالضبط: الطريقة ليست افتراضية ، لذا فإن الوصول من خلال المؤشرات نحو الطبقة الفائقة سينتهي بالطريقة القديمة (الطبقة العليا) بدلاً من الأسلوب الجديد (فئة فرعية).

إضافة "تجاوز" تفسر هذا بوضوح: من خلال هذا ، يخبر المرء المترجم أن هناك ثلاثة أمور تتوقع:

  1. هناك طريقة بالاسم نفسه في الطبقة الفائقة
  2. يتم تعريف هذه الطريقة في الطبقة العليا بأنها "افتراضية" (وهذا يعني ، يقصد إعادة كتابتها)
  3. الطريقة في الطبقة العليا لها نفس (المدخلات *) التوقيع كطريقة في الفئة الفرعية (طريقة إعادة الكتابة)

إذا كان أي منها غير صحيح ، فسيتم الإشارة إلى وجود خطأ.

* ملاحظة: معلمة الإخراج في بعض الأحيان مختلفة ، ولكن نوع ذات الصلة. اقرأ عن التحولات المتشابهة والمتناقضة إذا كانت مهتمة.


تعدد الأشكال هو قدرة مثيل الطبقة على التصرف كما لو كان مثالاً لطبقة أخرى في شجرة الميراث الخاصة بها ، وهي في الغالب واحدة من فئات الأسلاف. على سبيل المثال ، في جافا ترث جميع الطبقات من كائن. لذلك ، يمكنك إنشاء متغير من نوع الكائن وتعيين مثيل له من أي فئة.

التجاوز هو نوع من الوظائف التي تحدث في الفصل الذي يرث من فئة أخرى. تستبدل الدالة override الدالة الموروثة من الطبقة الأساسية ، ولكنها تقوم بذلك بطريقة يتم استدعاؤها حتى عندما يتظاهر مثيل من فئتها بنوع مختلف من خلال تعدد الأشكال. بالإشارة إلى المثال السابق ، يمكنك تعريف صفك الخاص وتجاوز وظيفة toString (). نظرًا لأن هذه الدالة موروثة من "كائن" ، فستظل متوفرة إذا قمت بنسخ مثيل من هذه الفئة إلى متغير نوع الكائن. عادة ، إذا قمت بالاتصال بـ String () على الفصل الدراسي الخاص بك أثناء التظاهر بأنه كائن ، فإن إصدار toString الذي سيطلق بالفعل هو الذي تم تعريفه على Object نفسه. ومع ذلك ، نظرًا لأن الدالة هي تجاوز ، يتم استخدام تعريف toString () من الفصل الدراسي حتى عند إخفاء النوع الحقيقي لنمط الفصل خلف تعدد الأشكال.

التحميل الزائد هو إجراء لتحديد عدة طرق بنفس الاسم ، ولكن باستخدام معلمات مختلفة. لا علاقة لها إما تجاوز أو تعدد الأشكال.





c++ c++11 inheritance override virtual-method