Kaip sukurti išimtis?

Taigi, turiu užduotį, susijusią su išimtimis, ir naudoju jas savo dabartinėje adresų knygelės programoje, kurioje daugiausia dėmesio skiriama daugeliui namų darbų užduočių. Nusprendžiau žaisti su išimtimis ir visais bandymais pagauti šį dalyką ir naudoti vėsią dizainą, ir tai, ką aš galiausiai turėsiu padaryti už savo užduotį per kelias savaites. Turiu darbo kodą, kuris puikiai patikrina išimtį, bet noriu sužinoti, ar yra būdas standartizuoti savo klaidų ataskaitos funkciją (pvz., Mano () skambutį):

Čia yra mano kodas:

 #include <iostream> #include <exception> using namespace std; class testException: public exception { public: virtual const char* what() const throw() // my call to the std exception class function (doesn't nessasarily have to be virtual). { return "You can't divide by zero! Error code number 0, restarting the calculator..."; // my error message } void noZero(); }myex; //<-this is just a lazy way to create an object int main() { void noZero(); int a, b; cout << endl; cout << "Enter a number to be divided " << endl; cout << endl; cin >> a; cout << endl; cout << "You entered " << a << " , Now give me a number to divide by " << endl; cin >> b; try { myex.noZero(b); // trys my exception from my class to see if there is an issue } catch(testException  // if the error is true, then this calls up the eror message and restarts the progrm from the start. { cout << te.what() << endl; return main(); } cout <<endl; cout << "The two numbers divided are " << (a / b) << endl; // if no errors are found, then the calculation is performed and the program exits. return 0; } void testException::noZero(int  //my function that tests what I want to check { if(b == 0 ) throw myex; // only need to see if the problem exists, if it does, I throw my exception object, if it doesn't I just move onto the regular code. } 

Ką norėčiau padaryti, kad mano funkcija () grąžintų vertę, priklausomai nuo to, kokio tipo klaida yra vadinama. Taigi, pavyzdžiui, jei sukėliau klaidą, kuri atrodė kaip viršutinis numeris, (a) norėdami pamatyti, ar tai buvo nulis, ir jei taip būtų, būtų nustatytas pranešimas, kad „negalite turėti nulinio skaitiklio“ , bet vis dar yra to, kas () funkcija. Štai pavyzdys:

  virtual const char* what() const throw() if(myex == 1) { return "You can't have a 0 for the numerator! Error code # 1 " } else return "You can't divide by zero! Error code number 0, restarting the calculator..."; // my error message } 

Akivaizdu, kad tai neveikia, bet ar yra būdas tai padaryti, todėl aš ne rašau kitą funkciją kiekvienam klaidos pranešimui?

20
24 апр. Charlie M yra nustatytas balandžio 24 d 2013-04-24 06:18 '13, 6:18, 2013-04-24 06:18
@ 4 atsakymai

Jūsų kode yra daug klaidingų nuomonių. Trumpas atsakymas yra „taip“, galite pakeisti, what() grąžinti norimą. Bet leiskite žingsnis po žingsnio.

 #include <iostream> #include <exception> #include <stdexcept> #include <sstream> using namespace std; class DivideByZeroException: public runtime_error { public: DivideByZeroException(int x, int y) : runtime_error( "division by zero" ), numerator( x ), denominator( y ) {} virtual const char* what() const throw() { cnvt.str( "" ); cnvt << runtime_error::what() << ": " << getNumerator() << " / " << getDenominator(); return cnvt.str().c_str(); } int getNumerator() const { return numerator; } int getDenominator() const { return denominator; } template<typename T> static T divide(const T n1, const T n2) { if ( n2 == T( 0 ) ) { throw DivideByZeroException( n1, n2 ); } return ( n1 / n2 ); } private: int numerator; int denominator; static ostringstream cnvt; }; ostringstream DivideByZeroException::cnvt; 

Pirma, iš exception gautas runtime_error yra rekomenduojama išimties klasė. Tai deklaruojama stdexcept antraštėje. Jums reikia tik inicijuoti savo konstruktorių su pranešimu, kurį ketinate grąžinti tuo, what() metodu.

Antra, atitinkamai turite paminėti savo klases. Suprantu, kad tai tik testas, bet aprašomasis pavadinimas visada padės skaityti ir suprasti jūsų kodą.

Kaip matote, aš pakeitiau konstruktorių, kad priimtume numerius, kad galėčiau pasidalinti išimta išimtimi. Išbandėte išimtį ... gerai, aš tai gerbiau, bet kaip statinę funkciją, kurią galima pavadinti iš išorės.

Ir galiausiai, what() metodas. Kadangi mes skirstome du skaičius, būtų malonu parodyti, kad du skaičiai, dėl kurių kilo išimtis. Vienintelis būdas tai pasiekti yra naudoti „ostringstream“. Čia mes darome ją statinį, todėl nėra problemos, kai rodyklė grąžinama į kamino objektą (ty su cnvt vietinis kintamasis įveda neapibrėžtą elgesį).

Likusi programos dalis yra daugiau ar mažiau nurodyta jūsų klausime:

 int main() { int a, b, result; cout << endl; cout << "Enter a number to be divided " << endl; cout << endl; cin >> a; cout << endl; cout << "You entered " << a << " , Now give me a number to divide by " << endl; cin >> b; try { result = DivideByZeroException::divide( a, b ); cout << "\nThe two numbers divided are " << result << endl; } catch(const DivideByZeroException  { cout << e.what() << endl; } return 0; } 

Kaip matote, ištrinau jūsų return main() nurodymą. Tai nėra prasminga, nes main() rekursyvumo negalima. Be to, tai yra klaida: tikitės pakartoti operaciją, kuri sukėlė išimtį, tačiau tai neįmanoma, nes išimtys kartojamos. Tačiau, norėdami pasiekti tą patį efektą, galite šiek tiek pakeisti šaltinio kodą:

 int main() { int a, b, result; bool error; do { error = false; cout << endl; cout << "Enter a number to be divided " << endl; cout << endl; cin >> a; cout << endl; cout << "You entered " << a << " , Now give me a number to divide by " << endl; cin >> b; try { result = DivideByZeroException::divide( a, b ); // trys my exception from my class to see if there is an issue cout << "\nThe two numbers divided are " << result << endl; } catch(const DivideByZeroException  // if the error is true, then this calls up the eror message and restarts the progrm from the start. { cout << e.what() << endl; error = true; } } while( error ); return 0; } 

Kaip matote, klaidos atveju vykdymas atliekamas tol, kol įvedamas „teisingas“ padalinys.

Tikiuosi, kad tai padės.

36
24 апр. Baltasarq atsakymas, pateiktas balandžio 24 d 2013-04-24 12:36 '13, 12:36 PM 2013-04-24 12:36

Tokio ilgio klaidai galite sukurti savo išskirtinę klasę.

 class MyException : public std::length_error{ public: MyException(const int  }; 
2
16 авг. Atsakyti Shashank Chaurasia 16 rug . 2017-08-16 16:08 '17, 16:08 pm 2017-08-16 16:08
 class zeroNumerator: public std::exception { const char* what() const throw() { return "Numerator can't be 0.\n"; } }; //... try { myex.noZero(b); // trys my exception from my class to see if there is an issue if(myex==1) { throw zeroNumerator(); // This would be a class that you create saying that you can't have 0 on the numerator } } catch(testException  { cout << te.what() << endl; return main(); } 

Visada turėtumėte naudoti std :: erand e. taip

 catch(std::exception  e) { cout<<e.what(); } 
2
24 апр. Atsakymas, kurį pateikė John Kemp Bal 24 2013-04-24 07:16 '13, 7:16, 2013-04-24 07:16

Turite atsižvelgti į klasės hierarchiją.

To priežastis gali būti neaiški, kai bandoma naudoti išimtis tik perduodant eilutę, tačiau tikrasis išimčių panaudojimo tikslas turi turėti pažangios išimties tvarkymo mechanizmą. Daugelis dalykų yra atliekami pagal C + + runtime aplinkos gaubtą, o skambučių kamino iškyla iškeliant iš „mesti“ į atitinkamą „sugavimą“.

Klasių pavyzdys gali būti:

 class DivisionError : public std::exception { public: DevisionError(const int numerator, const int divider) :numerator(numerator) , divider(divider) { } virtual const char* what() const noexcept { // ... } int GetNumerator() const { return numerator; } int GetDevider() const { return divider; } private: const int numerator; const int divider; }; class BadNumeratorError : public DivisionError { public: BadNumeratorError(int numerator, int divider) : DivisionError(numerator, divider) { } virtual const char* what() const noexcept { { // ... } }; class ZeroDeviderError : public DivisionError { public: ZeroDeviderError(int numerator, int divider) : DivisionError(numerator, divider) { } virtual const char* what() const noexcept { { // .... } }; 
  • Pateikdami skirtingas klases klaidoms, suteikiate kūrėjams galimybę tvarkyti įvairias klaidas tam tikru būdu (ir ne tik rodyti klaidos pranešimą)
  • Bazinės klasės suteikimas klaidų tipams leidžia kūrėjams būti lankstesniems - būti kuo konkretesni.

Kai kuriais atvejais jie turi būti konkretūs

 } catch (const ZeroDividerError  ex) { // ... } catch (const DivisionError  ex) { 

kitose ne

 } catch (const DivisionError  ex) { 

Kaip papildomos informacijos,

  • Jūs neturite sukurti savo išimčių objektų prieš mesti, kaip jūs. Nepriklausomai nuo jūsų ketinimų, tai paprasčiausiai nenaudinga - bet kuriuo atveju dirbate su objekto kopija sugavimo skyriuje (nesupainiokite prieigos per nuorodą)
  • Naudojant const nuorodą būtų geras catch (const testException > stilius catch (const testException > jei jums tikrai reikia keičiamo objekto.
0
01 авг. Arthur P. Golubev atsakymas 01 rug. 2017-08-01 14:30 '17, 14:30 val. 2017-08-01 14:30

Kiti klausimai, susiję su „ arba „ Klauskite“