native oder moderated für den windowseinstieg besser?



  • Nexus schrieb:

    woooh schrieb:

    aber was von den oben genanten Punkten brauchst du für RAII, Copy-and-swap, Safe bool usw. Gerade mal templates sind einigermaßen nützlich für smart pointers, container usw.

    Um RAII generisch zu behandeln, kommen oft Templates zum Zug (z.B. die von dir angesprochenen Smart-Pointer oder Container). Davon abgesehen kann man auch sonst viele Probleme sehr elegant mit Templates lösen, und Fehler von der Laufzeit auf die Compilezeit verlagern.

    Eine freie, überladene swap() -Funktion ist essentiell für ADL, ein Abstraktionskonzept von Namensräumen, das Präfixe nicht bieten.

    Die Standard Template Library brauche ich andauernd. Gerade die STL ist ein typisches Beispiel, wie modernes C++ aussehen kann: Dank Templates wird eine Entkopplung von Containern und Algorithmen möglich, wobei Iteratoren das Zwischenstück bilden. Zudem abstrahiert man von Low-Level-Mechanismen wie Zeigerarithmetik und manueller Speicherverwaltung.

    Generell kann man sich mit modernen C++-Errungenschaften von fehleranfälligen Altlasten aus C abwenden. Auch Makros mit ihren Problemen werden oft durch typsichere Alternativen ersetzt.

    Natürlich kann man nicht alles machen, wenn man nicht alles verwendet. Man kann statt mit Generizität vieles auch mit Objektorientierung machen, das ist dann mehr Java oder C# Style, aber von C with classes ist man immer noch weit entfernt. Ich hab das wxWidgets Zeugs noch nie verwendet und es kann sein, dass das C with classes ist.

    Nexus schrieb:

    Exceptionsicherheit wird damit natürlich ein Thema (das mit RAII aber gut zu bewältigen ist).

    Nö da musst du schon mehr aufwand reinstecken, der Destruktor wird garnicht aufgerufen, wenn im Konstruktor eine Exception fliegt.



  • woooh schrieb:

    Man kann statt mit Generizität vieles auch mit Objektorientierung machen, das ist dann mehr Java oder C# Style

    Das ist in C++ nicht ganz so einfach, weil z.B. nicht alle Typen von Object erben und nicht wenige Typen gar keine Klassen sind.

    Wie würdest du std::vector mit dynamischer Polymorphie implementieren, damit man sowohl int als auch eine eigene Klasse MyClass verwenden könnte? Du müsstest auf Typsicherheit verzichten, wie man es in Java vor den Generics getan hat. Du könntest nur Klassen verwenden, die von einer bestimmten Basisklasse abgeleitet sind.

    Wenn man wie wxWidgets Makros für Container verwendet, ist man teilweise sogar flexibler als mit Laufzeitpolymorphie. Weil eben die Typen zur Kompilierzeit bereits feststehen. Dafür hat man andere Nachteile.

    woooh schrieb:

    Nexus schrieb:

    Exceptionsicherheit wird damit natürlich ein Thema (das mit RAII aber gut zu bewältigen ist).

    Nö da musst du schon mehr aufwand reinstecken, der Destruktor wird garnicht aufgerufen, wenn im Konstruktor eine Exception fliegt.

    Nein, musst du nicht. Wieso sollte der Destruktor aufgerufen werden, wenn das Objekt noch nicht fertig konstruiert ist?

    struct MyClass
    {
        A* a;
        B* b;
    
        MyClass() : a(new A), b(new B)
        {
            // wenn der B-Konstruktor wirft, sind wir verloren.
        }
    };
    

    Mit RAII:

    struct MyClass
    {
        scoped_ptr<A> a;
        scoped_ptr<B> b;
    
        MyClass() : a(new A), b(new B)
        {
            // Problem gelöst
        }
    };
    

    Ohne Exceptions hat man im Konstruktor vor allem auch das Problem von anderen Ressourcenanforderungen, da man dem Aufrufer keinen Fehler mitteilen kann. Man müsste entweder in der Klasse ein Valid-Flag mitführen (unschön) oder nachträgliche Init-Funktionen bereitstellen (unschön).



  • Nexus schrieb:

    woooh schrieb:

    Nexus schrieb:

    Exceptionsicherheit wird damit natürlich ein Thema (das mit RAII aber gut zu bewältigen ist).

    Nö da musst du schon mehr aufwand reinstecken, der Destruktor wird garnicht aufgerufen, wenn im Konstruktor eine Exception fliegt.

    Nein, musst du nicht. Wieso sollte der Destruktor aufgerufen werden, wenn das Objekt noch nicht fertig konstruiert ist?

    struct MyClass
    {
        A* a;
        B* b;
    
        MyClass() : a(new A), b(new B)
        {
            // wenn der B-Konstruktor wirft, sind wir verloren.
        }
    };
    

    Mit RAII:

    struct MyClass
    {
        scoped_ptr<A> a;
        scoped_ptr<B> b;
    
        MyClass() : a(new A), b(new B)
        {
            // Problem gelöst
        }
    };
    

    Ohne Exceptions hat man im Konstruktor vor allem auch das Problem von anderen Ressourcenanforderungen, da man dem Aufrufer keinen Fehler mitteilen kann. Man müsste entweder in der Klasse ein Valid-Flag mitführen (unschön) oder nachträgliche Init-Funktionen bereitstellen (unschön).

    Schau dir mal die std::fstreams an, die werfen erst mal keine Exception. Exceptionsicherheit bei Zuweisungen gibts auch noch, das ist nicht nur RAII.



  • woooh schrieb:

    Schau dir mal die std::fstreams an, die werfen erst mal keine Exception.

    Die C++-Streams ermöglichen dem Benutzer, beide Wege zu gehen (und werden dafür auch teilweise kritisiert). Mit der exceptions() -Methode kann man Exceptions einschalten.

    woooh schrieb:

    Exceptionsicherheit bei Zuweisungen gibts auch noch, das ist nicht nur RAII.

    Natürlich ist Exceptionsicherheit nicht nur RAII. Aber RAII trägt enorm zur Umsetzung von Exceptionsicherheit (und generell zur Kapselung von fehleranfälligen oder Low-Level-Konstrukten) bei. Ohne RAII hast du oft hässliche If-Else- oder Try-Catch-Abfragen, die den Code sehr unübersichtlich machen. Alleine schon beim vorherigen Beispiel für 2 Variablen. Jede weitere würde den Code noch komplexer schachteln.

    MyClass()
    {
        a = new A;
        try
        {
            b = new B;
        }
        catch (...)
        {
            delete a;
            throw;
        }
    };
    


  • Nexus schrieb:

    woooh schrieb:

    Schau dir mal die std::fstreams an, die werfen erst mal keine Exception.

    Die C++-Streams ermöglichen dem Benutzer, beide Wege zu gehen (und werden dafür auch teilweise kritisiert). Mit der exceptions() -Methode kann man Exceptions einschalten.

    darum sag ich ja "erst mal"

    woooh schrieb:

    Exceptionsicherheit bei Zuweisungen gibts auch noch, das ist nicht nur RAII.

    Natürlich ist Exceptionsicherheit nicht nur RAII. Aber RAII trägt enorm zur Umsetzung von Exceptionsicherheit (und generell zur Kapselung von fehleranfälligen oder Low-Level-Konstrukten) bei. Ohne RAII hast du oft hässliche If-Else- oder Try-Catch-Abfragen, die den Code sehr unübersichtlich machen. Alleine schon beim vorherigen Beispiel für 2 Variablen. Jede weitere würde den Code noch komplexer schachteln.

    MyClass()
    {
        a = new A;
        try
        {
            b = new B;
        }
        catch (...)
        {
            delete a;
            throw;
        }
    };
    

    Hat auch keiner behauptet das man RAII nicht nehmen soll, sondern nur das es nicht reicht.


Anmelden zum Antworten