سؤال

ما هو أفضل نهج تغليف الأجسام وإدارة العمر ؟ على سبيل المثال:لدي الدرجة A, أن يحتوي على كائن من نوع ب و هو المسؤول الوحيد من أجل ذلك.

الحل 1, نسخة ب كائن لضمان فقط A قادرة على تنظيفه.

class A
{
    B *b;
public:
    A(B &b)
    {
        this->b = b.clone();
    }

    ~A()
    {
        delete b; // safe
    }
};

الحل 2, استخدام مباشرة مرت وجوه ، ونحن المخاطر المحتملة مزدوجة مجانا هنا.

class A
{
    B *b;
public:
    A(B *b)
    {
        this->b = b;
    }

    ~A()
    {
        delete b; // unsafe
    }
};

في الحالة الفعلية, الحل #2 شأنها أن تناسب أفضل.ولكن أنا أتساءل عما إذا كان هذا يعتبر سيء لأن شخص ما قد لا تعرفه عن سلوك A, حتى لو كانت موثقة.أستطيع أن أفكر من هذه السيناريوهات:

B *myB = new B();
A *myA = new A(myB);
delete myB; // myA contains a wild pointer now

أو ،

B *myB = new B();
A *firstA = new A(myB);
A *secondA = new A(myB); // bug! double assignment
delete firstA; // deletes myB, secondA contains a wild pointer now
delete secondA; // deletes myB again, double free

هل يمكنني تجاهل هذه القضايا إذا كنت بشكل صحيح وثيقة سلوك ؟ هل يكفي أن تعلن المسؤولية وترك الأمر إلى الآخرين من قراءة مستندات?كيف تمكنت في برنامج?

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

المحلول

يجب تحديد الكائن الخاص بك بحيث ملكية معاني الكلمات, قدر الإمكان, تعريف واجهة.كما ديفيد Thornley أشار std::auto_ptr هو مؤشر ذكية الاختيار للإشارة إلى نقل ملكية.تحديد الفئة الخاصة بك مثل ذلك:

class A
{    
    std::auto_ptr<B> b;
public:    
    A(std::auto_ptr<B> b)    
    {
        this->b = b;
    }
    // Don't need to define this for this scenario
    //~A()
    //{ 
    //   delete b; // safe
    //}
};

منذ عقد من الأمراض المنقولة جنسيا::auto_ptr هو أن الإحالة = نقل الملكية ، المنشئ الخاص بك الآن الدول ضمنا أنه كائن له ملكية المؤشر ب انها مرت.في الواقع ، إذا كان العميل يحاول أن تفعل شيئا مع std::auto_ptr<B> أنها تستخدم لبناء ما بعد البناء ، ستفشل العملية ، مؤشر لديهم سوف تكون غير صالحة.

نصائح أخرى

لم حذف أي شيء بنفسي إلا وأنا حقا.أن يؤدي إلى أخطاء.

المؤشرات الذكية صديقك. std::auto_ptr<> هو صديقك عندما كائن واحد يملك آخر و هو المسؤول عن حذفه عند الخروج من نطاق. boost::shared_ptr<> (أو الآن ، std::tr1::shared_ptr<>) هو صديقك عندما يكون هناك يحتمل أكثر من كائن واحد يعلق على كائن آخر و تريد الكائن حذف عندما لا يوجد ما يشير إلى ذلك.

لذا إما استخدام الحل 1 مع auto_ptr, أو 2 مع الحل shared_ptr.

في حالة كتابة التعليمات البرمجية أن شخصا آخر سوف تستخدم في وقت لاحق, يجب معالجة هذه القضايا.في هذه الحالة سوف تذهب إشارة بسيطة العد (ربما مع المؤشرات الذكية).النظر في المثال التالي:

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

المزيد حول هذا الموضوع: إشارة العد.

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

إذا كنت استنساخ كل من A1 و A2 الاحتفاظ إشارات إلى ب ، ثم ب عمر لا يتم التحكم فيها بالكامل من قبل A.كان يتم تبادلها بين مختلف A.الاستنساخ ب يضمن واحد-إلى-واحد العلاقة بين وبس, والتي سوف يكون من السهل ضمان مدى الحياة الاتساق.

إذا كان الاستنساخ ب ليس خيارا ، ثم تحتاج إلى تجاهل مفهوم أن مسؤولية ب عمر.إما كائن آخر سوف تحتاج إلى إدارة مختلف ب ، أو سوف تحتاج إلى تنفيذ أسلوب مثل إشارة العد.

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

لا استنساخ الأمور دون داع أو "مجرد أن تكون آمنة".

بدلا أعرف الجهة التي تقع عليها مسؤولية حذف شيء:إما عن طريق الوثائق ، أو عن طريق المؤشرات الذكية ...على سبيل المثال ، إذا كان لدي create وظيفة instantiates شيء و عودة المؤشر إلى أنه لا حذف ، بحيث أنه من غير الواضح إلى أين مواطنيهما هذا الشيء من أي وقت مضى من المفترض أن يتم حذفها ، ثم بدلا من create'ق العودة عارية المؤشر قد تحدد create's نوع الإرجاع العودة المؤشر الواردة في بعض نوع من مؤشر ذكية.

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