سؤال

قل لدي فئة تسمى "قاعدة"، وفئة تسمى "مشتقة" وهي فئة فرعية من الأساس والوصول إلى الأساليب المحمية وأعضاء القاعدة.

ما أريد القيام به الآن هو جعله حتى لا توجد فئات أخرى من الفئة الفرعية المستمدة. في Java يمكنني تحقيق ذلك بإعلان الفئة المشتقة "النهائي". هل هناك بعض خدعة C ++ التي يمكن أن تعطيني نفس التأثير؟

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

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

المحلول

اعتبارا من C ++ 11، يمكنك إضافة الكلمة الرئيسية النهائية (من الناحية الفنية معرف خاص لأنها ليست في الواقع كلمة رئيسية) إلى صفك، على سبيل المثال

class Derived final
{
...

يمكنك قراءة المزيد عن الكلمة الرئيسية النهائية في http://en.wikipedia.org/wiki/c++11#explicit_overrides_and_final.

نصائح أخرى

يمكنك الحصول على منشئ خاص ل 'Derivedووظيفة إنشاء ثابتة عامة

أسهل طريقة لحظر الفئة الفعلية هي جعل المنشئ الخاص:

class Foo
{
private:
    Foo() {}

public:
    static Foo* CreateFoo() { return new Foo; }
};

تحرير: شكرا ل Insidera للإشارة إلى أن هذا يحتاج إلى طريقة مصنع ثابت

لا توجد طريقة بسيطة ونظيفة للقيام بذلك.

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

في نهاية المطاف، هل أنت يحتاج لإثارة الفئة الفئة غير ممكنب أليس ذلك جيدا بما يكفي للإشارة إلى أن "المستمدة من هذه الفئة هي فكرة سيئة"؟

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

حماية الكود الخاص بك ضد مورفي، وليس machiavelli. ؛)

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

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

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

// Forward declaration of class Derived
template< class COMMON
        , class EXTRA1
        , class EXTRA2 >
class Derived;


// Definition of general class template Base
template< class SUBCLASS
        , class COMMON >
class Base
{
private:
    Base() {}
};


// Definition of partial specialisation of template class Base to open up
// access to the constructor through friend declaration.
template< class COMMON
        , class EXTRA1
        , class EXTRA2 >
class Base< Derived< COMMON, EXTRA1, EXTRA2 >
          , COMMON >
{
private:
    Base() {}

    friend class Derived< COMMON, EXTRA1, EXTRA2 >;
};


// Definition of class Derived
template < class COMMON
         , class EXTRA1
         , class EXTRA2 >
class Derived
    : public Base< Derived< COMMON, EXTRA1, EXTRA2 >
                 , COMMON >
{
public:
    static Derived* create() { return new Derived; }

private:
    Derived() : Base< Derived< COMMON, EXTRA1, EXTRA2 >
                    , COMMON >()
    {
    }
};


// Definition of class HonestDerived.
// It supplies itself as the SUBCLASS parameter to Base.
template < class COMMON
         , class EXTRA1
         , class EXTRA2 >
class HonestDerived
    : public Base< HonestDerived< COMMON, EXTRA1, EXTRA2 >
                 , COMMON >
{
public:
    HonestDerived() : Base< HonestDerived< COMMON, EXTRA1, EXTRA2 >
                          , COMMON >()
    {
    }
};


// Definition of class DishonestDerived
// It supplies Derived rather than itself as the SUBCLASS parameter to Base.
template < class COMMON
         , class EXTRA1
         , class EXTRA2 >
class DishonestDerived
    : public Base< Derived< COMMON, EXTRA1, EXTRA2 >
                 , COMMON >
{
public:
    DishonestDerived() : Base< Derived< COMMON, EXTRA1, EXTRA2 >
                             , COMMON >()
    {
    }
};


template< class COMMON, class EXTRA1, class EXTRA2 >
class DerivedFromDerived
    : public Derived< COMMON, EXTRA1, EXTRA2 >
{
public:
    DerivedFromDerived() : Derived< COMMON, EXTRA1, EXTRA2 >()
    {
    }
};

// Test partial specialisation gives Derived access to the Base constructor
Derived< int, float, double >* derived
    = Derived< int, float, double >::create();

// Test that there is no access to the Base constructor for an honest subclass
// i.e. this gives a compiler error
HonestDerived< int, float, double > honestDerived;

// Test that there is no access to the Base constructor for a dishonest subclass
// i.e. this gives a compiler error
DishonestDerived< int, float, double > dishonestDerived;

// Test that there is no access to the Derived constructor
// i.e. this gives a compiler error
DerivedFromDerived< int, float, double > derivedFromDerived;

تم اختبار هذا الرمز مع GCC 4.3.2.

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

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