سؤال

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

CMyClass obj; // A
obj.DoStuff();

if ( somebool )
{
    CMyClass obj; // B
    obj.DoStuff();
}

obj.DoOtherStuff();

يبدو كما لو أن dootherstuff () إما يتم على "B" ، أو أن B.Dostuff () يعمل في بعض الأحيان في الواقع على - أي i dostuff () يتم استدعاؤه فعليًا على OBJ الأول.

هل يمكن أن يحدث هذا؟ لا أعتقد أنني حصلت على تحذير للمترجم (لقد أصلحت الرمز الآن على أمل أن يساعد ذلك). يبدو جداً من المحتمل أن يكون هذا الجزء من الكود الفعلي هو المكان الذي أحاول العثور عليه ، ولكن يمكن بالطبع أن يكون هناك أسباب أخرى لم أكتشفها بعد.

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

المحلول

الرمز ، كما هو مكتوب ، يجب أن يعمل. أول مكالمة إلى DoStuff() وآخر مكالمة إلى DoOtherStuff() لا يمكن إرسالها إلا A.

الدعوة إلى DoStuff() داخل if(somebool) { } لا يمكن إرسال الكتلة إلا B.

من اساسي:

3.3.2 النطاق المحلي

  1. الاسم المعلن في كتلة (6.3) محلية لتلك الكتلة. يبدأ نطاقه المحتمل عند إعلانه (3.3.1) وينتهي في نهاية منطقتها التصريحية.

و:

3.3.7 الاسم الاختباء

  1. يمكن إخفاء الاسم بإعلان صريح لهذا الاسم نفسه في منطقة إعلانية متداخلة أو فئة مشتقة (10.2).

ومع ذلك ، ربما هذا ليس ما كان منوي من قبل مؤلف هذا الرمز. إذا كان للمتغيرات نفس الاسم ، فربما يكون القصد أن يكون لديك مثيل واحد فقط من هذا المتغير ، و B مثيل تم إنشاؤه داخل الحلقة هو خطأ. هل مررت بالمنطق لمعرفة ما إذا كان مثيلًا ثانية منطقيًا؟

نصائح أخرى

إلا إذا obj.DoStuff() يقوم بإجراء تغيير على بعض الأشياء العالمية ، كما يشير فالنتين

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

CMyClass obj; // A
obj.DoStuff();
if ( somebool )
{ 
 CMyClass obj; // B  
 obj.DoStuff();  //does on B
 ::obj.DoStuff(); //does on A
}
obj.DoOtherStuff(); //this will call A because B is destroyed

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

إذا كنت تستخدم GCC ، يمكنك (في رأيي -) استخدام -wshadow ، والتي ستنبعث من تحذيرات في حالات مثل تلك الموجودة في مثالك ، والتي غالبًا ما تكون حشرة خفية للغاية.

ومع ذلك ، كما قال العديد من الأشخاص الآخرين بالفعل ، فإن الكود الذي لصقه صحيح ، ويفعل ما تتوقعه ، وليس سلوكًا غير محدد.

لا ، لا يمكن أن يحدث.

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

الخطأ في مكان آخر.

قد يكون الكود الخاص بك صحيحًا بشكل نحلي ، ولكن ماذا تفعل الأساليب؟ يمكن أن يتسبب فائض المكدس في سلوك مخيف مثل مراقبة ، على سبيل المثال.

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