لا يسمح بالوظائف المتداخلة ولكن لماذا يسمح باستخدام نماذج الوظائف المتداخلة؟ [C ++

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

سؤال

انا كنت قراءة السؤال المرتبط الذي يقودني إلى طرح هذا السؤال.

النظر في التعليمات البرمجية التالية

int main()
{
    string SomeString();
}

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

int main()
{
    string Some()
    {
        return "";
    }
}

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

لقد اكتشفت ما يلي صالح.

int main()
{ 
  string SomeFun();
  SomeFun();
  return 0;
}

string SomeFun()
{
  std::cout << "WOW this is unexpected" << std::endl;
}

هذا هو أيضا مربكة. كنت أتوقع وظيفة بعض المرح() سيكون لدينا نطاق فقط في رئيسي. وبعد ولكنني كنت مخطئا. لماذا يسمح التحويل البرمجي بتجميع التعليمات البرمجية مثل ما سبق؟ هل هناك أي مواقف في الوقت الحقيقي حيث الكود مثل ما سبق المنطقي؟

أي أفكار؟

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

المحلول

النموذج الأولي الخاص بك هو فقط "إعلان إلى الأمام". يرجى مراجعة مقالة ويكيبيديا.

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

يمكنك في الواقع أن تعلن النموذج الأولي الزائف، على سبيل المثال "char therefun ()" واستخدامها في جميع أنحاء الرئيسية. ستحصل فقط على خطأ عندما يحاول رابطك العثور على جسم وظيفة Bogus الخاصة بك. لكن مترجمك سيكون رائعا معه.

هناك الكثير من الفوائد. عليك أن تتذكر هيئة الوظيفة ليست دائما في نفس ملف التعليمات البرمجية المصدر. . ذلك بدلا من ذلك.

أتمنى أن يساعدك هذا.

نصائح أخرى

تماما كملاحظة جانبية، يحتوي C ++ 03 على طريقة مستديرة لتحديد الوظائف المحلية. يتطلب إساءة استخدام ميزة الطبقة المحلية:

int main()
{
    struct Local
    {
        static string Some()
        {
            return "";
        }
    };
    std::cout << Local::Some() << std::endl;
}

هذه اتفاقية من C - مثل الكثير - والتي اعتمدت C ++.

القدرة على الإعلان عن وظيفة داخل وظيفة أخرى في ج هي قرار أن معظم المبرمجين يرواون أن ينظروا مؤسفين وغير ضروري. خاصة مع تصميم OOP الحديث حيث توجد تعريفات الوظيفة أصغر نسبيا مما هي عليه في C.

إذا كنت ترغب في الحصول على وظائف موجودة فقط في نطاق وظيفة أخرى، فإن خياران دفعة :: Lambda. و C ++ 1X لامبادا.

لماذا إعلانك

void f() {
    void g(); g();
}

هو أفضل من هذا واحد

void g();
void f() {
    g();
}

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

void f() {
    int g; 
    // oops, ::g is shadowed. But we can work around that
    {
        void g(); g();
    }
}

بالطبع، في C ++ يمكننا استدعاء وظيفة g استخدام its_namespace::g() - ولكن في الأيام الخوالي من ج، لم يكن ذلك ممكنا، وهذا الشيء سمح للمبرمج بالوصول إلى الوظيفة. لاحظ أيضا أنه في حين أنه من الناحية النحوية ليست هي نفسها، فإن ما يلي دلالة كما يعلن أيضا وظيفة داخل نطاق محلي، حيث يستهدف بالفعل نطاق مختلف.

int main() {
    using std::exit;
    exit();
}

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

struct X { friend void f() { std::cout << "WoW"; } };
int main() { void f(); f(); } // works!

على الرغم من إعلان الوظيفة (وتعريف!) من f حدث في نطاق X, ، أصبحت الكيان (الوظيفة نفسها) عضوا في مساحة الاسم المرفوعة.

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

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

string foo()
{
  string ret = someString();  // Error
  return ret; 
}

int main(int argc,char**argv)
{
   string someString();
   string s = somestring(); // OK
   ...
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top