أكملت الفصل الثالث من الاستثناءات ومعالجة الأخطاء، مقتطف
المنشئون والاستثناءات
يتم ذكر هذا الموضوع غالبًا في مجتمع C++، ولكن يبدو أن لا أحد قد اهتم به في مجتمع دلفي. ربما بسبب خصائص اللغة، لا يحتاج مبرمجو دلفي إلى القلق بشأن هذه المشكلة. لكنني أعتقد أنه يجب على مبرمجي دلفي أيضًا فهم هذه المشكلة ومعرفة ما توفره لنا اللغة لتسهيل تجاهلها. وكما يقول المثل: "عندما تكون محاطًا بالنعم، يجب أن تعرف النعم". نحن نعلم أن مُنشئ الفئة ليس له قيمة إرجاع إذا فشل المُنشئ في إنشاء الكائن، فمن المستحيل الاعتماد على إرجاع رمز الخطأ. فكيف يمكن التعرف على فشل المنشئ في البرنامج؟ الطريقة الأكثر "قياسية" هي: طرح استثناء. فشل المنشئ يعني فشل بناء الكائن، لذا بعد طرح الاستثناء، كيف سيتم التعامل مع هذا الكائن "نصف الميت"؟ هنا، أعتقد أنه من الضروري أن يكون لديك فهم لكيفية تعامل C++ مع هذا الموقف قبل القراءة. في C++، لا يتم استدعاء المدمر بعد أن يطرح المنشئ استثناءً. يعتبر هذا الأسلوب معقولًا لأنه لم يتم إنشاء الكائن بالكامل في الوقت الحالي. إذا قام المنشئ ببعض العمليات مثل تخصيص الذاكرة، وفتح الملفات، وما إلى ذلك، فإن فئة C++ تحتاج إلى أن يكون لها أعضاؤها الخاصون لتذكر الإجراءات التي تم تنفيذها. بالطبع، يعد هذا أمرًا مزعجًا للغاية بالنسبة لمنفذي الفصل، لذلك يتجنب منفذو فئة C++ بشكل عام طرح الاستثناءات في المُنشئين (يمكنك توفير وظيفة عضو مثل Init وUnInit، والتي يتم استدعاؤها للمنشئ أو عميل الفصل). فشل التهيئة). الحل الذي يقدمه كل كتاب C++ كلاسيكي هو استخدام المؤشرات الذكية (Auto_ptr من الفئة القياسية لـ STL). في Object Pascal، تصبح هذه المشكلة بسيطة للغاية، ولا داعي للقلق بشأنها. إذا طرحت فئة Object Pascal استثناءً في المنشئ، فسيقوم المترجم تلقائيًا باستدعاء مدمر الفئة (نظرًا لأنه لا يُسمح بتحميل المدمر بشكل زائد، فمن المؤكد أن هناك مدمرًا واحدًا فقط، لذلك لن يتم الخلط بين المترجم بين مدمرات متعددة). يتم تدمير الكائنات الأعضاء بشكل عام في المدمر، وتضمن طريقة Free () عدم استدعاء المدمر على كائنات لا شيء (أي الكائنات الأعضاء التي لم يتم إنشاؤها بعد)، أثناء جعل التعليمات البرمجية موجزة وجميلة، كما أنه يضمن السلامة. type MyClass = classPRivateFStr : PChar; // مؤشر السلسلة publicconstructor Create();destructor Destroy();end;constructor MyClass.Create();beginFStr := StrAlloc(10); FStr، 'ABCDEFGHI')؛ رفع الاستثناء.إنشاء ('خطأ')؛ // رمي استثناء، بدون سبب، hahaend;destructor A.Destroy();beginStrDispose(FStr); // تحرير الذاكرة في destructor WriteLn('Free Resource');end;varObj : TMyClass;i : integer;begintryObj : = TMyClass.Create ();Obj.Free();WriteLn('نجح');exceptObj := nil;WriteLn('Failed');end;Read(i); // إيقاف الشاشة مؤقتًا لملاحظة نهاية النتائج قيد التشغيل. في هذا الرمز، يطرح المُنشئ استثناءً، وتكون نتيجة التنفيذ: Free ResourceFailed في هذا الوقت" يتم إنتاج إخراج "الموارد المجانية" بواسطة المترجم الذي يستدعي المدمر تلقائيًا. لذلك، إذا أخبرتك وثائق الفصل أو مؤلف الفصل أن مُنشئ الفصل قد يطرح استثناءً، فتذكر أن تغلفه بمحاولة...إلا! إن الطرق المختلفة التي يتعامل بها C++ وObject Pascal مع الاستثناءات التي يطرحها المنشئون هي في الواقع تجسيد لأفكار التصميم في اللغتين. تلتزم لغة C++ بأسلوب لغة C وتركز على الكفاءة، ويترك كل شيء للمبرمج ولا يقوم المترجم بأي إجراءات غير ضرورية. يرث Object Pascal أسلوب Pascal ويركز على المعنى الجمالي للبرنامج، ويساعد المترجم المبرمجين على إكمال العمل المعقد.