examples - لماذا لا يجب الإعلان عن طرق البناء في C++؟



function in c++ pdf (2)

" لماذا يمكنني إجراء مفهوم مماثل في البنية ، ولكن لا تصرخ في ذلك؟"

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

  • أمر متوقع ، مع
  • الحد الأدنى من الفوضى.

بالنسبة إلى الطلبات التي يمكن التنبؤ بها ، يكون لدى الأشخاص أساليب خاصة بهم ، وهناك جزء من "الفن" ، ولكن على سبيل المثال ، استخدم كل محدد وصول على الأكثر ، ودائمًا ، public قبل protected قبل private ، ثم ضمن تلك التي أضع فيها عادةً ملفات typedef ، أو const ، أو الصانعين ، destructors ، mutating / non-const ، وظائف const ، static s ، friend s ....

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

ويختلف ذلك عن الوظائف التي لا تنتمي إلى فئة - حيث يستخدم الأشخاص الذين يحبون البرمجة من أعلى لأسفل الإعلانات الدالة وإخفاء التعريفات لاحقًا في الملف - في ذلك:

  • الأشخاص الذين يفضلون أسلوبًا برمجيًا من الأسفل إلى الأعلى لن يقدرون أن يكونوا مجبرين على أن يكون لديهم إعلانات منفصلة في الفصول الدراسية أو يتخلون عن الممارسة المتعارضة التي لا يمكن التضارب فيها ،

  • من المرجح أكثر أن تحتوي الدرجات الدراسية على العديد من الوظائف القصيرة جدًا ، ويعود ذلك إلى حدٍ كبير إلى أنها توفر التغليف وتلف الكثير من بيانات العضو التافهة أو توفر الحمولة الزائدة للمُشغِّل وصب المشغلين والمبدعين الضمنيين وميزات الراحة الأخرى غير ذات الصلة بغير OO ، وظائف غير الأعضاء. وهذا يجعل الفصل القسري المستمر للإعلانات والتعريفات أكثر إيلاما للعديد من الطبقات (ليس كثيرا في الواجهات العامة حيث قد تكون التعريفات في ملف منفصل ، ولكن بالتأكيد على سبيل المثال الطبقات في مساحات الأسماء المجهولة التي تدعم وحدة الترجمة الحالية).

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

https://ffff65535.com

خذ على سبيل المثال ، التعليمة البرمجية التالية:

#include <iostream>
#include <string>

int main()
{
    print("Hello!");
}

void print(std::string s) {
    std::cout << s << std::endl;
}

عند محاولة بناء ذلك ، أحصل على ما يلي:

program.cpp: In function ‘int main()’:
program.cpp:6:16: error: ‘print’ was not declared in this scope

مما يجعل من المنطقي.

فلماذا يمكن أن أقوم بمفهوم مماثل في البنية ، ولكن لا تصرخ به؟

struct Snake {
    ...

    Snake() {
        ...
        addBlock(Block(...));
    }

    void addBlock(Block block) {
        ...
    }

    void update() {
        ...
    }

} snake1;

ليس فقط لا أحصل على التحذيرات ، ولكن البرنامج في الواقع يجمع! بدون أخطاء! هل هذه مجرد طبيعة البنى؟ ماذا يحصل هنا؟ بوضوح تم استدعاء addBlock(Block) قبل الإعلان عن الطريقة على الإطلاق.


معيار C ++ 3.4.1:

0.4:

يجب الإعلان عن الاسم المستخدم في النطاق العالمي ، خارج أي وظيفة أو فئة أو مساحة اسم معلنة من قبل المستخدم ، قبل استخدامه في النطاق العالمي.

هذا هو السبب في أنه لا يمكن استخدام المتغيرات والوظائف العالمية قبل الإعلان السابق.

0.5:

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

نفس الشيء مكتوب مرة أخرى فقط كما الفقرة .4 مقيد صراحة مقولتها إلى "العالمية" ، هذه الفقرة تقول الآن "بالمناسبة ، صحيح كذلك في أسماء الناس ..."

0.7:

يجب الإعلان عن الاسم المستخدم في تعريف الفئة X خارج هيئة دالة عضو أو تعريف الفئة المتداخلة 29 بإحدى الطرق التالية: - قبل استخدامها في الفئة X أو أن تكون عضوًا في فئة أساسية من X (10.2) أو - إذا كانت X عبارة عن فئة متداخلة من الصنف Y (9.7) ، قبل تعريف X في Y ، أو يجب أن تكون عضوًا في صنف أساسي من Y (ينطبق هذا البحث بدوره على فئات Y للإحاطة ، بدءًا من الطبقة الداخلية المرافقة) ، أو 30 أو - إذا كانت X فئة محلية (9.8) أو فئة متداخلة من فئة محلية ، قبل تعريف الفئة X في قالب يرفق تعريف الفئة X ، أو - إذا كانت X عبارة عن عضو في مساحة الاسم N ، أو عبارة عن فئة متداخلة من فئة عضو في N ، أو فئة محلية أو فئة متداخلة داخل فئة محلية لوظيفة عضو في N ، قبل تعريف الفئة X في مساحة الاسم N أو في أحد مساحات الأسماء في N.

أعتقد أن هذا يتكلم عن كل الكود الذي لا يقف في كود cpu المنفذة (على سبيل المثال ، التعليمة البرمجية).

وأخيرًا الجزء المثير للاهتمام:

3.3.7 نطاق الصف [basic.scope.class]

1 تصف القواعد التالية نطاق الأسماء المُعلنة في الفئات.

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

2) يجب أن يشير الاسم N المستخدم في الفئة S إلى نفس الإعلان في سياقه وعندما تتم إعادة تقييمه في النطاق المكتمل لـ S. لا يلزم إجراء تشخيص بسبب انتهاك هذه القاعدة.

3) إذا كانت إعادة ترتيب إعلانات الأعضاء في أي فئة تعطي برنامجًا بديلاً صالحًا بموجب (1) و (2) ، فهذا البرنامج غير سليم ، ولا يلزم إجراء تشخيص.

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

القول الفعال ، في الفصل ، هو الإعلان بدا في متابعة بطريقة تجميع على مرحلتين.





declare