لماذا نحتاج بالفعل إلى الميراث الخاص أو المحمي في لغة C++؟

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

سؤال

في C ++ ، لا يمكنني التفكير في حالة أود أن أرث فيها خاصًا/محميًا من فئة أساسية:

class Base;
class Derived1 : private Base;
class Derived2 : protected Base;

هل هو مفيد حقا؟

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

المحلول

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

class Engine {
 public:
   Engine(int numCylinders);
   void start();                 // Starts this Engine
};

class Car {
  public:
    Car() : e_(8) { }             // Initializes this Car with 8 cylinders
    void start() { e_.start(); }  // Start this Car by starting its Engine
  private:
    Engine e_;                    // Car has-a Engine
};

للحصول على نفس الدلالة، يمكنك أيضًا كتابة فئة السيارة على النحو التالي:

class Car : private Engine {    // Car has-a Engine
 public:
   Car() : Engine(8) { }         // Initializes this Car with 8 cylinders
   using Engine::start;          // Start this Car by starting its Engine
}; 

ومع ذلك، فإن هذه الطريقة في العمل لها عدة عيوب:

  • نيتك أقل وضوحا بكثير
  • يمكن أن يؤدي إلى الميراث المتعدد المسيئ
  • فهو يكسر تغليف فئة المحرك حيث يمكنك الوصول إلى أعضائها المحميين
  • يُسمح لك بتجاوز الأساليب الافتراضية للمحرك، وهو أمر لا تريده إذا كان هدفك هو تكوين بسيط

نصائح أخرى

والخاصة يمكن أن تكون مفيدة في عدد غير قليل من الظروف. فقط واحد منهم السياسات ما يلي:

هل الدرجة جزئية قالب التخصص الجواب على هذه المشكلة تصميم؟ .

ومناسبة أخرى حيث أنه من المفيد هو لا سمح النسخ وتعيين:

struct noncopyable {
    private:
    noncopyable(noncopyable const&);
    noncopyable & operator=(noncopyable const&);
};

class my_noncopyable_type : noncopyable {
    // ...
};

ولأننا لا نريد أن المستخدم لديه مؤشر من نوع noncopyable* إلى هدفنا، نستمدها من القطاع الخاص. أن تحصي ليس فقط لnoncopyable، ولكن العديد من هذه الفئات الأخرى أيضا (السياسات هي الأكثر شيوعا).

ونماذج الميراث العام IS-A.
نماذج الميراث غير العامة IN-شروط-OF-IS تنفيذها.
نماذج الاحتواء HAS-A، وهو ما يعادل المنفذة IS--IN-شروط-OF.

سوتر حول موضوع . وهو ما يفسر عندما كنت اختيار الميراث غير العامة على الاحتواء للحصول على تفاصيل التنفيذ.

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

ويستخدم الميراث الخاص معظمها لسبب الخطأ. الناس استخدامها لالمنفذة IS--IN-شروط-OF، كما هو مبين في جواب سؤال سابق، ولكن في تجربتي انها دائما أكثر نظافة للحفاظ على نسخة بدلا من يرث من الصف. الجواب في وقت سابق آخر، واحد عن CBigArray، تقدم نموذجا مثاليا لهذا نموذج مضاد.

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

ولقد استعملت كل من الإرث الخاص ومحمية في نقطة واحدة أو أخرى.

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

الإرث

والمحمية مفيد خصوصا عندما يكون لديك الفئة الأساسية التي تستمد وظائف مفيدة من فئة أخرى ولكن تريد فقط الطبقات المشتقة منها لتكون قادرة على استخدامها.

لقد قمت ذات مرة بتنفيذ هياكل البيانات هذه كفئات:

  • قائمة مرتبطة
  • مجموعة عامة (ملخص)
  • مصفوفة بسيطة (ترث من المصفوفة العامة)
  • مجموعة كبيرة (يرث من مجموعة عامة)

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

template <typename T>
class CBigArray : public IArray, private CLnkList {
    // ...
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top