في C ++ ، هل وظيفة افتراضية تلقائيًا إذا كانت تتجاوز وظيفة افتراضية؟

StackOverflow https://stackoverflow.com/questions/1404797

  •  05-07-2019
  •  | 
  •  

سؤال

أتوقع ذلك إذا foo تم إعلانه في الفصل D, ، ولكن لم يتم وضع علامة افتراضية ، فإن الكود التالي سوف يستدعي تنفيذ foo في D (بغض النظر عن النوع الديناميكي من d).

D& d = ...;
d.foo();

ومع ذلك ، في البرنامج التالي ، هذا ليس هو الحال. هل يمكن لأي شخص أن يشرح هذا؟ هل الأسلوب افتراضي تلقائيًا إذا تجاوزت وظيفة افتراضية؟

#include <iostream>

using namespace std;

class C {
public:
        virtual void foo() { cout << "C" << endl; }
};

class D : public C {
public:
        void foo() { cout << "D" << endl; }
};

class E : public D {
public:
        void foo() { cout << "E" << endl; }
};

int main(int argc, char **argv)
{
        E& e = *new E;
        D& d = *static_cast<D*>(&e);
        d.foo();
        return 0;
}

إخراج البرنامج أعلاه هو:

E
هل كانت مفيدة؟

المحلول

القياسي 10.3.2 (class.virtual) يقول:

إذا تم الإعلان عن وظيفة العضو الظاهري VF في قاعدة فئة وفي فئة مشتقة ، مشتقة مباشرة أو غير مباشرة من القاعدة ، فإن وظيفة العضو VF مع نفس الاسم وقائمة المعلمات نفسها كما تم الإعلان هو أيضًا افتراضي (سواء تم إعلانه أم لا) ويتجاوز*

الحاشية: وظيفة تحمل نفس الاسم ولكن قائمة معلمات مختلفة (جملة أكثر) كدالة افتراضية ليست بالضرورة افتراضية ولا تتغلب عليها. يعد استخدام المحدد الافتراضي في إعلان الوظيفة الغالبة قانونية ولكنها زائدة عن الحاجة (لها دلالات فارغة). لا يعتبر التحكم في الوصول (Clause Class.Access) في تحديد الإفراط. --- نهاية فونوت

نصائح أخرى

قد تكون الإجابة السريعة لا ، لكن الإجابة الصحيحة هي نعم

لا يعرف C ++ عن إخفاء الوظيفة ، لذا فإن تجاوز الوظيفة الافتراضية دون علامات الكلمات الرئيسية الافتراضية التي تعمل بشكل افتراضي أيضًا.

أنت لا تقوم بإنشاء أي نسخة من كائن E ووضعه في D. لذلك D.FOO () يتبع السلوك متعدد الأشكال الطبيعي والمكالمات المستمدة من الفئة. تصبح الطريقة التي يُعلن أنها افتراضية في الفئة الأساسية افتراضية تلقائيًا في الفئة المشتقة أيضًا.

يتصرف الإخراج ("E") تمامًا كما يتوقع المرء أن يتصرف.

السبب: النوع الديناميكي (أي وقت التشغيل) من هذا المرجع هو E. أنت تقوم بعمل ثابت إلى D ، لكن هذا لا يغير النوع الفعلي للكائن بالطبع.

هذه هي الفكرة ذاتها وراء الأساليب الافتراضية والإرسالات الديناميكية: ترى سلوك النوع الذي كنت مثيلًا له ، وهو E ، في هذه الحالة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top