في C ++، متى يمكن أن تكون متغيران من نفس الاسم مرئيا في نفس النطاق؟

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

سؤال

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

#include <iostream>

int *a;

int* f()
{
  int *a = new int;
  return a;
}

int main()
{
  std::cout << a << std::endl << f() << std::endl;
  return 0;
}

إخراجها (مترجمة مع G ++):

0
0x602010

لقد بحثت في مراجع بضع (Stroustrup ومرجع C ++ الكامل) ولا يمكنك العثور على أي شيء حول متى ولماذا يسمح بذلك. أعلم أنه ليس ضمن نطاق محلي واحد، على الرغم من ذلك.

متى ولماذا يسمح بذلك؟ هل هناك استخدام جيد لهذا البناء؟ كيف يمكنني الحصول على G ++ لتحذيري حول هذا الموضوع؟ هل محطات التحويل البرمجيات الأخرى حول هذا الموضوع؟

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

المحلول

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

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

نصائح أخرى

لماذا يسمح بذلك: هذا صحيح تماما.

عندما تكون ضمن دالة F () الخاصة بك، فأنت تحدد نطاق محلي. تتجاوز النطاقات المحلية النطاق العالمي، لذلك تحديد متغير "A" هناك "يخفي" العالم int *a;

هذا صحيح تماما، لكنني أعتقد ذلك -Wall تحصل على تحذير فقط عند ظهور المعلمة.

إذا كنت تريد تحذيرات عندما تظل أي نوع المتغير، يمكنك استخدام هذا، من g++ الصفحة اليدوية:

   -Wshadow
       Warn whenever a local variable shadows another local variable, 
       parameter or global variable or whenever a built-in function is 
       shadowed.

لاحظ أن -Wshadow لم يتم تضمينها -Wall بشكل افتراضي.

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

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

#include  <iostream>


int a = 5;
int main()
{
    int a = 6;

    std::cout << a << "\n" << ::a << "\n";
            // Local
                           // global
}

للإجابة عند السماح بهذا: أساسا في أي نطفة متداخلة.

على سبيل المثال:

void foo() {
    int a;
    {
        int a;
    }
}

class Base {
    int a;
};
class Derived: public Base {
    int a; // Yes, the name Base::a is visible in the scope of Derived, even if private
};

class Foo() {
    int a;
    Foo(int a) : a(a) { } // Works OK
};

using std::swap;
void swap(MyClass& lhs, MyClass& rhs);
// Not strictly a variable, but name lookup in C++ happens before determining 
// what the name means.

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

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

كما ذكر آخرون، هذا قانونية تماما، ولا لبس فيه للمترجم.

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

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