2017-12-28 4 views
-2

ich Problem mit Ausnahmen haben:Ausnahmen & C-Strings

#include <iostream> 
#include <cstring> 
#include <exception> 

class except :public std::exception 
{ 
    char* err; 
public: 
    except(const char* s) noexcept 
    { 
     err = new char[strlen(s) + 1]; 
     strcpy(err, s); 
     err[strlen(s)] = 0; //is it necessary?? 
    } 
    virtual const char* what() noexcept 
    {return err;} 
    virtual ~except() noexcept 
    {delete err;} 
}; 

double div(const double& a, const double& b) noexcept 
{ 
    if (b == 0.0) 
     throw except("DIVIDED BY 0"); 
    return a/b; 
} 

int main() 
{ 
    try 
    { 
     std::cout << div(5.0, 0.0); 
    } 
    catch (std::exception &ex) 
    { 
     std::cout << ex.what(); 
    } 
    return 0; 
} 

Ich will "Geteilt durch 0" drucken, aber ich bekomme:

terminate called after throwing an instance of 'except' 
    what(): std::exception 
Aborted 

Process returned 134 (0x86) 

Soll ich noexcept in jeder Funktion/member-Funktion, die keine Ausnahmen auslöst?

Ist err[strlen(s)] = 0 erforderlich? (In außer :: außer (const char * s))

+1

Warum Sie std :: string nicht verwenden? Besser: Ableiten von std :: runtime_error. –

+2

1) Weißt du, was C-Saiten sind? Sie sind nullterminierte Strings. "_Is' err [strlen (s)] = 0' notwendig? _ "Nein, nicht wirklich, seit [std :: strcpy] (http://en.cppreference.com/w/cpp/string/byte/strcpy) enthält es, wenn Sie die Zeichenfolge kopieren. Eine solche Linie verursacht jedoch keinen Schaden. 2) 'löschen err;' ist undefiniertes Verhalten. Es sollte gelöscht werden als 'delete [] err;', da es 'new'ed mit' new [] 'ist. –

+0

Sie verwenden Ausnahmen, ein etwas mittleres bis fortgeschrittenes Thema in C++, aber Sie verwenden C-Style-Strings. Warum? – PaulMcKenzie

Antwort

2

möchte ich "Geteilt durch 0" drucken, aber ich erhalte: genannt beenden, nachdem eine Instanz des Werfens 'außer'

double div(const double& a, const double& b) noexcept 

Sie behaupten, dass Sie keine Ausnahme werfen werden, aber Sie lügen. Das Ergebnis ist der Aufruf von std :: terminate, wenn Sie tatsächlich werfen.

+0

Nach dem Entfernen von 'noexcept':' ex.what() 'gibt' std :: exception' zurück. Wenn ich außer ': public std :: exception 'in': public std :: runtime_error 'ändere, funktioniert es, warum? – inter22

2

Das Problem ist eigentlich zweifach. Erstens, wie @ manni66 vorschlägt, sollte div nicht noexcept deklariert werden und dies verursacht einen Laufzeitfehler, aber das Entfernen löst das Problem nicht.

Das zweite Problem ist, dass what erklärt wurde:

virtual const char* what() noexcept; 

während sie in std::exception als deklariert ist:

virtual const char* what() const noexcept; 

und diese Differenz in Unterschrift bedeutet, dass, wenn es durch die Behandlungsroutine für std::exception gefangen ruft es std::exception::what() und nicht except::what()

Ein paar Erwähnenswerte Punkte:

  1. Stellen Sie sicher, dass Ihre Funktionsüberladungen genau mit denen in der Basisklasse übereinstimmen.
  2. Wenn Sie erwarten, dass eine bestimmte Art von Ausnahme ausgelöst wird, versuchen Sie, diese zuerst mit einem bestimmten Handler abzufangen und verwenden Sie zur besseren Übersichtlichkeit einen geeigneten Namen für die Ausnahme.
  3. Wie andere erwähnt haben, versuchen Sie bitte, die std::string Klasse zu verwenden, wenn Sie können. Es wird die Dinge einfacher und sicherer machen. Obwohl in diesem Fall, wie sich Punkt zwei entzieht, ein String-Mitglied nicht wirklich notwendig ist, da die Klasse spezifisch genug ist, um keine weitere Qualifikation zu benötigen.
  4. Erstellen Sie keine Ausnahmeklasse, es sei denn, es wird ein bestimmter Wert hinzugefügt (obwohl der Wert, kann einfach sein, dass Sie gezielt eine bestimmte Art von Ausnahme abfangen und auf eine bestimmte Weise behandeln.) Wenn Sie mehr wollten allgemeine Ausnahme dann std::runtime_error oder in diesem Fall std::overflow_error würde anständige Wahlen sein und beide nehmen ein std::string als Argument zum Konstruktor, also keine Notwendigkeit, Ihre eigene Ausnahmeklasse zu verursachen.

Zum Beispiel:

#include <exception> 
using namespace std; 


class divide_by_zero : public std::exception 
{ 
public: 
    virtual const char* what() const noexcept { return "DIVIDED BY 0"; } 
}; 

double div(const double& a, const double& b) 
{ 
    if (b == 0.0) 
     throw divide_by_zero(); 
    return a/b; 
} 

int main() 
{ 
    try 
    { 
     std::cout << div(5.0, 0.0); 
    } 
    catch (divide_by_zero &ex) 
    { 
     std::cout << ex.what(); 
    } 
    catch (std::exception &ex) 
    { 
     std::cout << ex.what(); 
    } 
    return 0; 
} 

Ausgang:

DIVIDED BY 0 
+0

Ich weiß, dass ich nicht C-style string verwenden sollte und vermeiden Sie das Erstellen eigener Ausnahmen Klassen, wenn es nicht notwendig ist. Ich will nur wissen, warum es nicht funktioniert. Das Hinzufügen von 'noexcept' löst das Problem nicht, die Ausgabe ist immer noch 'std :: exception'. (Ich weiß, dass ich 'throw std :: runtime_error (" DIVIDED BY 0 ") einfach verwenden kann) – inter22

+0

Nimm einfach deinen Code und (a) entferne' noexcept' _only_ von der Div-Funktion und (b) stelle sicher, dass dein ' what() 'hat genau die gleiche Signatur wie' std :: exception' (dh muss const sein), auch ohne die obigen zusätzlichen Vorschläge sollte es funktionieren –