سؤال

في C++ ، يمكنك تحديد وظيفة قد تكون أو لا رمي استثناء باستخدام استثناء محدد.على سبيل المثال:

void foo() throw(); // guaranteed not to throw an exception
void bar() throw(int); // may throw an exception of type int
void baz() throw(...); // may throw an exception of some unspecified type

أنا المشكوك فيه عن الواقع باستخدام لهم بسبب التالية:

  1. المترجم لا فرض استثناء محددات في أي طريقة صارمة ، لذلك فوائد ليست كبيرة.من الناحية المثالية, كنت ترغب في الحصول على خطأ ترجمة.
  2. إذا وظيفة ينتهك استثناء محدد ، أعتقد معيار السلوك هو إنهاء البرنامج.
  3. في VS.Net ، فإنه يعامل رمي(X) كما رمي (...) ، لذلك الالتزام القياسية ليست قوية.

هل تعتقد استثناء محددات يجب استخدامها ؟
الرجاء الإجابة بـ "نعم" أو "لا" وتقديم بعض الأسباب لتبرير الجواب.

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

المحلول

لا.

هنا العديد من الأمثلة لماذا:

  1. قالب مدونة من المستحيل أن يكتب مع استثناء المواصفات ،

    template<class T>
    void f( T k )
    {
         T x( k );
         x.x();
    }
    

    النسخ قد رمي ، المعلمة عابرة قد رمي ، x() قد رمي بعض استثناء مجهول.

  2. استثناء-المواصفات تميل إلى منع التمدد.

    virtual void open() throw( FileNotFound );
    

    قد تتطور إلى

    virtual void open() throw( FileNotFound, SocketNotReady, InterprocessObjectNotImplemented, HardwareUnresponsive );
    

    هل يمكن حقا أن أكتب

    throw( ... )
    

    الأول هو عدم الموسعة ، والثاني هو مفرطة في الطموح و الثالث هو حقا ما تعنيه عند كتابة وظائف افتراضية.

  3. التعليمات البرمجية القديمة

    عند كتابة التعليمات البرمجية التي تعتمد على مكتبة أخرى, كنت لا أعرف حقا ما عند شيء يذهب على نحو خاطئ.

    int lib_f();
    
    void g() throw( k_too_small_exception )
    { 
       int k = lib_f();
       if( k < 0 ) throw k_too_small_exception();
    }
    

    g سيتم إنهاء, عندما lib_f() يلقي.هذا هو (في معظم الحالات) لا ما كنت تريد حقا. std::terminate() لا ينبغي أبدا أن يسمى.فمن الأفضل دائما أن نترك تعطل التطبيق مع استثناء غير معالج ، التي يمكنك من خلالها استرجاع كومة-أثر ، مما بصمت/بعنف يموت.

  4. كتابة التعليمات البرمجية التي تقوم بإرجاع الأخطاء الشائعة ويلقي في مناسبات استثنائية.

    Error e = open( "bla.txt" );
    if( e == FileNotFound )
        MessageUser( "File bla.txt not found" );
    if( e == AccessDenied )
        MessageUser( "Failed to open bla.txt, because we don't have read rights ..." );
    if( e != Success )
        MessageUser( "Failed due to some other error, error code = " + itoa( e ) );
    
    try
    {
       std::vector<TObj> k( 1000 );
       // ...
    }
    catch( const bad_alloc& b )
    { 
       MessageUser( "out of memory, exiting process" );
       throw;
    }
    

ومع ذلك ، عندما المكتبة الخاصة بك فقط يلقي الخاصة بك الاستثناءات ، يمكنك استخدام استثناء مواصفات الدولة القصد الخاص.

نصائح أخرى

تجنب استثناء المواصفات في C++.الأسباب التي تعطي في السؤال هي بداية جيدة لماذا.

انظر عشب ساتر هو "عملي ننظر استثناء المواصفات".

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

في ذلك وأعتقد أنه يستحق وصف استثناء الضمانات.

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

استثناء الضمانات

أي ضمان:

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

الضمانة الأساسية:

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

قوية تضمن:(ويعرف أيضا باسم المعاملات ضمان)

هذا يضمن أن الأسلوب بنجاح
أو استثناء سيتم طرح والكائنات الدولة لن تتغير.

لا رمي الضمان:

طريقة يضمن أن لا استثناءات مسموح نشر من طريقة.
جميع المتلفات ينبغي أن تجعل هذا الضمان.
| N. B.إذا كان استثناء يهرب وهو المدمر بينما الاستثناء هو بالفعل نشر
| التطبيق سيتم إنهاء

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

فقط مفيدة استثناء محدد هو "رمي ()" ، كما في "لا رمي".

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

أيضا, أعتقد أن استخدامها قد انتقدت في الوقت الحالي مشاريع C++0x القياسية.

استثناء المواصفات ليست رائعة من الأدوات المفيدة في C++.ومع ذلك ، هناك /هو/ الاستخدام الجيد بالنسبة لهم ، إذا كان جنبا إلى جنب مع الأمراض المنقولة جنسيا::غير متوقع.

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

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

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

وإلا لا تجد أنه مفيدة بشكل خاص إلى استخدام أي شيء ولكن throw() للإشارة إلى أنه لا يلقي أي استثناءات.

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

http://blogs.msdn.com/larryosterman/archive/2006/03/22/558390.aspx

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

نعم السلوك المتوقع من غير المحدد استثناء التي القيت من وظيفة مع استثناء محددات هو الدعوة الى إنهاء().

وسوف نلاحظ أيضا أن سكوت مايرز يتناول هذا الموضوع في أكثر فعالية C++.له فعالية C++ و أكثر فعالية C++ ينصح الكتب.

نعم, إذا كنت في الوثائق الداخلية.أو ربما كتابة libary أن الآخرين سوف تستخدم ، حتى يتمكنوا من معرفة ما يحدث دون استشارة الوثائق.إلقاء أو رمي يمكن اعتبار جزء من API, تقريبا مثل قيمة الإرجاع.

وأنا أتفق, فهي ليست مفيدة حقا على فرض صحة جافا النمط في مترجم, لكنه أفضل من لا شيء أو تعليق العشوائية.

أنها يمكن أن تكون مفيدة من أجل وحدة الاختبار بحيث عند كتابة الاختبارات كنت أعرف ما يمكن توقعه وظيفة لرمي عندما يفشل, ولكن لا يوجد تطبيق المحيطة بهم في المترجم.أعتقد أنها رمز إضافية ليست ضرورية في C++.والتي سبق لك أن تختار كل ما عليك أن تكون متأكدا من أنك تتبع نفس الترميز القياسية عبر المشروع وأعضاء الفريق حيث أن التعليمات البرمجية لا تزال قابلة للقراءة.

من المقال:

http://www.boost.org/community/exception_safety.html

"ومن المعروف أن من المستحيل كتابة استثناء-آمنة عامة الحاوية." هذا الادعاء كثيرا ما سمعت مع الإشارة إلى مقال توم كارجيل [4] الذي كان يستكشف مشكلة استثناء-السلامة عام كومة القالب.في المادة كارجيل يثير العديد من مفيدة الأسئلة لكن للأسف فشل تقديم حل مشكلته.1 ويختتم مما يدل على أن الحل قد لا يكون ممكنا.إلا أن المادة لم تقرأ من قبل العديد من "إثبات" أن المضاربة.لأنها نشرت كانت هناك العديد من الأمثلة على استثناء-آمنة عامة مكونات من بينها C++ المكتبة القياسية الحاويات.

وفي الواقع يمكن أن نفكر في طرق لجعل قالب الطبقات استثناء آمنة.إلا إذا كنت لا تملك السيطرة على جميع الفئات الفرعية ثم قد يكون لديك مشكلة على كل حال.أن تفعل هذا واحد يمكن أن تخلق typedefs في الفصول الدراسية التي تحدد استثناءات من قبل مختلف فئات قالب.هذا أعتقد أن المشكلة هي دائما تغير اتجاهها بعد ذلك بدلا من تصميم من البداية, و أعتقد أن هذا هو الحمل الحقيقي العقبة.

استثناء المواصفات = القمامة ، اسأل أي Java developer فوق سن 30

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