سؤال

لدي التسلسل الهرمي للفئة التالية في C ++:

class Base {
    virtual void apply() = 0;
};

class Derived : public Base {
    virtual void apply() {
        // implementation here that uses derived_specialty
    }

    virtual void derived_specialty() = 0;
};


class Implementation : public Derived {   
    virtual void derived_specialty() {
        // implementation
    }
};

أرغب في ضمان أن الفصول الدراسية على مستوى التنفيذ لا توفر تنفيذها الخاص للتطبيق، وأنها تقوم فقط بتنفيذ المشتقات. هل هناك أي طريقة لضمان عدم تنفيذ الفصول الدراسية من المشتقات، بحيث يتم استخدام تنفيذ التطبيق المشتق :: تطبيق؟ فهمي هو أنه في C ++، أصبحت طريقة افتراضية في الفئة الأساسية هي الظاهري طوال الطريق إلى أسفل التسلسل الهرمي للميراث، ولكن إذا كانت هناك أي حيل في C ++ لإنجازها، فسوف أكون مهتما بالسمع عنها.

أنا دائما فوجئت بالأشياء المسموح بها بواسطة C ++، لذلك اعتقدت أنه كان يستحق السؤال. :)

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

المحلول

يمكنك نوع القيام بذلك عن طريق التكوين:

class Base {
    virtual void apply();
};

class Derived : public Base {

    class IImplementation {
        virtual void derived_specialty() = 0;
    };

    IImplementation& m_implementation;

    Derived(IImplementation& implementation)
        : m_implementation(implementation)
    {}

    virtual void apply() {
        // implementation here that uses m_implementation.derived_specialty
    }

};


class Implementation : Derived::IImplementation {   
    virtual void derived_specialty() {
        // implementation
    }
};

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

نصائح أخرى

يمكنك تنفيذ طبقة مفوضة بدلا من تخصص

class Derived : public Base
{
    Derived()

    void apply() 
    {
        //whatever, delegate to impl class instance
        impl->apply_specialization();
    }


    Impl* impl;
};

class Impl : public WhateverImplInterface
{
      void apply_specialization(){}
};

ثم لا يملك التنفيذ الوصول إلى وظيفة تطبيق ويتم فصله عن التسلسل الهرمي. ثم يتم بعد ذلك المعلمة الفئة المشتقة بمثابة مثيل من فئة الجهاز.

جعل التقييد واضح في وثائقك.

"أود أن أضمن أن الفصول الدراسية على مستوى التنفيذ لا توفر تنفيذها الخاص للتقديم".

لا يمكنك ذلك.

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

ما كنت تبحث عن هو البيان النهائي Java غير موجود في C ++، أليس كذلك؟

يمكنك إنشاء قاعدة :: تطبيق غير الظاهري واستخدم نمط طريقة القالب داخل القاعدة أيضا.

تشرح هذه المقالة مزايا هذه الممارسة:
http://www.gotw.ca/publications/mill18.htm.

يمكنك وضع تأكيد في Destructor للتأكد تطبيق لم يتم تجاوزه:

class Base {
    virtual void apply() = 0;
};

class Derived : public Base {
    virtual void apply() {
        // implementation here that uses derived_specialty
    }
    virtual ~Derived() {
        assert(this->apply == Derived::apply);
    }
    virtual void derived_specialty() = 0;
};


class Implementation : public Derived {   
    virtual void derived_specialty() {
        // implementation
    }
};

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

حاول استخدام نمط طريقة القالب

ويكيبيديا لديه مثال C ++.

لا يغير التغليف، لكنه يحسن التصميم حتى لا تحتاج إلى ذلك.

هناك دائما تعديل المعدلات:

 class base {
      protected: virtual void real_apply() = 0;
 };
 class derived : public base {
      void real_apply();
 public:
      apply() { real_apply(); }
 };
 class other : public derived {
      void func() {
          apply();      // this is ok
          real_apply(); // this is a compile time error
      }
 };
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top