An agile journey and beyond

Kategorie: C++

Tricks and tips with c++.

Was spricht gegen Exceptions in C++?

Obwohl es Exceptions im C++ Standard schon etliche Jahre gibt, werden diese in größeren Projekten oft nicht eingesetzt. Im folgenden Artikel möchte ich das Für und Wider erörtern und mit gängigen Vorurteilen aufräumen.

try {
    funktion();
   ...
} catch (const std::invalid_argument& e) {
    std::cerr << "Falsches Argument:"  << e.what() << std::endl;
} catch (const std::range_error& e) {
    std::cerr << "Ungültiger Bereich:" << e.what() << std::endl;
} catch (...) {
    std::cerr << "Sonstiger Fehler" << std::endl;
}

Gängige Vorurteile

  1. Die Behandlung von Ausnahmen ist codeintensiver (mehr Schreibarbeit)
    Falsch. Ein sinnvolles try/catch braucht ist sogar weniger Code als ein sinnvolles if/else if/elsefür alle möglichen Fehlercodes. Fehlercodes werden aber oft nicht vollständig überprüft oder gar ganz weggelassen, was der Qualität des Codes nicht gerade zuträglich ist. Exceptions dagegen zwingen zu einer durchdachten Fehlerbehandlung.
  2. Exceptions machen den Code langsam
    Falsch. Wenn Exceptions richtig eingesetzt werden, sollten sie für Ausnahmen im Programmablauf verwendet werden. Die Ausführungsgeschwindigkeit des "Gut"-Pfades (in dem keine Ausnahmen geworfen werden) leidet nicht darunter. Wenn also die Exception die Ausnahme und nicht die Regel ist, hat man nichts zu befürchten. Weiterlesen

C++ Schlüsselwort „explicit“

Mit dem C++ Schlüsselwort „explicit“ kann man dem Compiler implizite Typumwandlungen verbieten. Dies kann manchmal ja auch ungewollt passieren, wie folgendes Beispiel zeigt:

#include 
#include 
struct MyClass
{
    MyClass(const char* name) : m_Name(name) {}
    virtual ~MyClass() {}
    const char* Who() const { return m_Name; }
private:
    const char* m_Name;
};

struct MyExplicitClass
{
    explicit MyExplicitClass(const char* name) : m_Name(name) {}
    virtual ~MyExplicitClass() {}

    const char* Who() const { return m_Name; }
private:
    const char* m_Name;
};


int main()
{
    MyClass A("a");
    MyExplicitClass B("b");
              
    A = "c";  // ok, hier funktioniert das, aber war das auch so gewollt? 
              // Auf den ersten Blick zu durchschauen ist diese Zuweisung jedenfalls nicht.

    B = "d";  // error C2679: Binärer Operator '=': Es konnte kein Operator gefunden werden, 
              // der einen rechtsseitigen Operanden vom Typ 'const char [2]' akzeptiert (oder
              // keine geeignete Konvertierung möglich)

    std::cout << "A: " << A.Who() << std::endl;
    std::cout << "B: " << B.Who() << std::endl;

    return 0;
}

Pure virtual function call

Eine abstrakte Klasse in C++ hat mindestens eine pure virtual Funktion (gekennzeichnet durch virtual ... = 0). Diese Funktionen können per Definition nicht direkt aufgerufen werden, da sie keine Implementierung haben (auch per Definition). Sollte die Methode dennoch aufgerufen werden, wird das Programm (von der Runtime) mit der Fehlermeldung „Pure virtual function call“ abgebrochen. Weiterlesen