Klassenfrage :)



  • @omggg sagte in Klassenfrage 🙂:

    Denn das Supermarktbeispiel ist total irrelevant... wichtig sind die Paradigmen.

    Bitte was? So ein Buch sollte vermitteln, dass man sinnvolle Datenstrukturen aufbaut, die man nachvollziehen kann. Wenn man modelliert, dass ein Wurstbrot ein Supermarkt ist (zum Glück nicht "isst", aber warum eigentlich nicht, im Supermarkt gibts Nahrungsmittel, also kann man doch einen Supermarkt auch essen - ist dieselbe Logik...), dann ist Hopfen und Malz verloren. Das war ja auch nur ein Beispiel von dem Mist, der in dem damaligen Buch stand. Vielleicht ist das neue Buch besser. Wer weiß. Zu befürchten ist, dass so offensichtliche Dinge behoben sind, aber man es generell trotzdem nicht nutzen sollte.

    Ich sag mal so: ich hatte mal einen Kollegen, der dieses Buch zum Lernen verwendet hatte. Er war nur wenige Monate mein Kollege.



  • @wob sagte in Klassenfrage 🙂:

    Ich sag mal so: ich hatte mal einen Kollegen, der dieses Buch zum Lernen verwendet hatte. Er war nur wenige Monate mein Kollege.

    Kann dieses Zitat jemand in die Warnung vor seinen Büchern mit einbauen?

    Danke.


  • Gesperrt

    @wob

    Ach herrje, ich hab den Wolf mit dem Breymann verwechselt ... Ich muss aber dazu sagen, dass ich beide Bücher nicht zur Gänze gelesen habe ... insofern kann ich mir kein Urteil anmaßen.

    Aber mal Butter bei die Fische ... ist Vererbung, also genauer gesagt das Decorator pattern, nicht einfach nur syntaktischer Zucker? Heikle These, das stimmt, aber hier werden auch Alternativen genannt: https://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)#Issues_and_alternatives

    kurz: Rollen!



  • @wob @omggg
    Als Anwender lernt man c++ weil man was programmieren will, nicht um eine akademische Auseinandersetzung über Klassendesing führen zu können. Der Vorwurf gegen Jürgen Wolf mit seinem Handbuch zu c++, das OOP-Thema (Von dem ich selbst erfolgreich nicht viel verstehe) unzureichen behandelt zu haben, scheint mir trivial in Abetracht eurer Kritik 😃



  • @EL-europ sagte in Klassenfrage 🙂:

    Als Anwender lernt man c++ weil man was programmieren will, nicht um eine akademische Auseinandersetzung über Klassendesing führen zu können. Der Vorwurf gegen Jürgen Wolf mit seinem Handbuch zu c++, das OOP-Thema (Von dem ich selbst erfolgreich nicht viel verstehe) unzureichen behandelt zu haben, scheint mir trivial in Abetracht eurer Kritik

    Dann tu, was du nicht lassen kannst.

    Eine Recherche von 15 MInuten lieferte mir aber schon folgende Dinger:

    Insbesondere die explizite Typumwandlung per reinterpret_cast und der dynamic_cast sind ein relativ kompliziertes und weitreichendes Thema. Sie werden daher an dieser Stelle nicht weiter behandelt.

    Quelle: "Grundkurs C++", 2021

    Das erklärt sich, so glaube ich, von selbst. Und ein Zeilen später wird der C Cast erklärt und dass dieser gefahrlich ist. Kein Beispiel warum.

    struct Programm
    {
    	DatabaseInterface &db_:
    	
    	void run()
    	{
    		std:: cout << db_.getData() << "\n";
    	}
    }
    

    Quelle: C++: "Das umfassende Handbuch zu Modernen C++. Über 1.000 Seiten Profiwissen aktuell zum Standard C++20"

    Kein Wort zum Thema Lebenszeiten, dass jede Programm Instanz an die Lebenszeit von db_ gebunden ist und dies eigentlich ein gefährlicher Programmierstil ist.



  • @Quiche-Lorraine
    Natürlich ist die akademische Auseinandersetzung mit OOP oder sonstiger Informatik wichtig, aber ist es nich für jeden schwierig diese leicht verständlich darzulegen? (mach es besser wer kann) Und die größere Kritik verdient sich Jürgen Wolf durch seine Praxisfernen Beispiele. Für Informatiker mögen "foo" und "bar" zuordenbar sein doch "normale" Anwender haben damit Probleme. Ich weiß aus dem Stehgreif nicht ob Jürgen Wolf diese Begriffe verwendet, aber seine Beispiele sind Praxisfern im Handbucg zu c++11 und dem Grundkurs C aus dem Rheinwerkverlag. (Zeitarbeiter, Namen und Personalnummern sind nur für wenige Menschen von bedeutung)Ich habe keine Informatik-Literatur über die triviale hinaus gelesen um mir ein umfassendes weder Detailliertes Bild der OOP-Thematik verschaffen zu können, vielleicht ist die Kritik gerechtfertigt, doch die Praxisferne ist das größere Problem.



  • Natürlich will euch nicht die konkrete Lösung vorenthalten, auch wenn sie "erschreckend" 😃 einfach ist

    class gui{
    public:
      std::function<void(int)> button_funktion
      gui(std::function<void(int)> funktion){
        button_funktion = funktion;
      }
      void onMouseOver(int x, int y, int taste){
        if(x=bla) button_funktion(blub);
      }
    }
    
    void buttonKlick(int val){
      if(val<1) tu das;
      else if(val<2)tuwas anderes;
    }
    
    void loop(){
      while(1){
        if(maus_x==gui_x) gui->onMouseOver(maus_x, maus_y, taste);
        else if(maus_x==on_exit) exit(0);
      }
    }
    
    gui *myGui;
    int main(){
      myGui = new gui(buttonKlick);
    }
    


  • @EL-europ sagte in Klassenfrage 🙂:

    Wie wäre es damit?

    #include <functional>
    #include <iostream>
    
    class gui {
    public:
        std::function<void(int)> button_funktion;
    
        gui(std::function<void(int)> funktion) {
            button_funktion = funktion;
        }
    };
    
    void buttonKlick(int val) {
        if (val < 1) 
            std::cout << "tu das";
        else if (val < 2)
            std::cout << "tuwas anderes";
    }
    
    
    int main() {
        gui myGui(buttonKlick);
        gui myGui2([](int val) {
            if (val < 1)
                std::cout << "tu das";
            else if (val < 2)
                std::cout << "tuwas anderes";
            });
    }
    


  • @Quiche-Lorraine
    Ich will auch ausserhalb der main() durch andere Funktionen auf gui zugreifen können, deshalb hab ich sie als "*gui" "Zeiger" deklariert.



  • @EL-europ sagte in Klassenfrage 🙂:

    Ich will auch ausserhalb der main() durch andere Funktionen auf gui zugreifen können, deshalb hab ich sie als "*gui" "Zeiger" deklariert.

    Und ein Parameter kommt da nicht in Frage weil?

    BTW:
    Man sollte ggf. auch das Klassendesign anpassen.



  • @EL-europ

    BTW: Warum nutzt du überhaupt new und nicht z.B. std::unique_ptr?



  • @Quiche-Lorraine
    die Funktionalität einer GUI hab ich mit diesem Klassendesing vollends umsetzen können. Was fehlt ist ein nutzerfreundliches Verfahren bis zu 10 oder auch 100 tausend Farbwerte an die jeweiligen Parameter zu bekommen.
    Da bin ich jetzt grad am spielen mit dem bisher errichtem um selbst "Erfahrung" zu sammeln.



  • @Quiche-Lorraine sagte in Klassenfrage 🙂:

    @EL-europ

    BTW: Warum nutzt du überhaupt new und nicht z.B. std::unique_ptr?

    was ist anderst daran, ausser das ich es nicht kenne?



  • @Quiche-Lorraine
    bei Interesse: https://github.com/momefilo/mandelbrodt. Ist aber alles nackter Code ohne Kommentare



  • @EL-europ sagte in Klassenfrage 🙂:

    was ist anderst daran, ausser das ich es nicht kenne?

    Naja, das Schlüsselwort new allokierst du eine Ressource. Doch wer gibt diese wieder frei?

    Wenn du diese Frage nicht sauber beantworten kannst, bist du auf dem besten Weg ein Speicherloch in dein Programm zu reißen. Und dann crasht dein Programm im besten Fall. Im schlimmsten Fall dein Rechner, weil dein Program auf einmal mehrere Gigabyte RAM frisst.

    Deswegen nutzt man die RAII Technik:

    https://en.cppreference.com/w/cpp/language/raii

    Kein malloc, new,... sondern nur std::unique_ptr, std::vector,...



  • @Quiche-Lorraine
    Da triffst du den Nagel zumindest nah am Kopf:
    Ich allociere in einer Klasse c-arrays, wenn ich Objekte dieser Klasse in std::vector speichere und diese Arrays im Destruktor mit free() freigebe, funktionieren entsprechende Methoden der Objekte in std::vector nicht mehr. Ich geb zu das die c-arrays und c-threads "quick n dirty" Lösungen sind weil ich meine thread-Lösung nicht einfach in c++ threads umgesetz bekam, wie den Rest des Codes



  • @EL-europ sagte in Klassenfrage 🙂:

    bei Interesse: https://github.com/momefilo/mandelbrodt. Ist aber alles nackter Code ohne Kommentare

    Sorry, wenn ich das mal sage. Aber dein Code is grausam:

    • Du nutzt ungeniert new. Wer gibt myApples.push_back(*new _AppleData); wieder frei`?
    • Warum allokierst du eigentlich ständig Sachen, welche doch auch auf dem Stack liegen könnten?
    • Wann darf ein Pointer bei dir NULL sein? Warum nutzt du kein nullptr?
    • Du missachtest komplett die Rule of Five! (https://en.cppreference.com/w/cpp/language/rule_of_three)
      -> Du musst die Move Semantik beachten! (https://en.cppreference.com/w/cpp/language/move_constructor)
    • Warum nutzt du malloc und nicht std::vector?
    • Warum hast du einen Quicksort geschrieben und nutzt nicht std::sort?
    • char iterText[17]; printf(iterText, "I-Werte % 8d", countsOfIter); -> Das ist unter C++ ein völlig veralteter Programmierstil und eine potenzielle Buffer Overflow Sicherheitslücke. Nutze std::format!

    Ein paar Cppcheck Sachen:

    • Apple.cpp Line 127: Common realloc mistake: 'iterMembers' nulled but not freed upon failure
    • Apple.cpp Line 65: '(void*)tmp_x' is of type 'void *'. When using void pointers in calculations, the behaviour is undefined. Arithmetic operations on 'void *' is a GNU C extension, which defines the 'sizeof(void)' to be 1.
    • Apple.cpp Line 182: Member variable '_Apple::xpos' is not initialized in the constructor. Member variables of native types, pointers, or references are left uninitialized when the class is instantiated. That may cause bugs or undefined behavior.
    • _Userinterface.cpp Line 152: Buffer is accessed out of bounds: text
    • _Userinterface.cpp Line 8: When an object of a class is created, the constructors of all member variables are called consecutively in the order the variables are declared, even if you don't explicitly write them to the initialization list. You could avoid assigning 'callback' a value by passing the value to the constructor in the initialization list.

    Das ist jetzt leider für dich ein wenig heftig und das tut mir auch Leid. Aber lerne daraus!

    Vergiss das bisher gelernt und lerne aus einem richtig gutem C++ Buch.



  • @Quiche-Lorraine sagte in Klassenfrage 🙂:

    @EL-europ sagte in Klassenfrage 🙂:

    bei Interesse: https://github.com/momefilo/mandelbrodt. Ist aber alles nackter Code ohne Kommentare

    Sorry, wenn ich das mal sage. Aber dein Code is grausam:

    • Du nutzt ungeniert new. Wer gibt myApples.push_back(*new _AppleData); wieder frei`?
    • Warum allokierst du eigentlich ständig Sachen, welche doch auch auf dem Stack liegen könnten?
    • Wann darf ein Pointer bei dir NULL sein? Warum nutzt du kein nullptr?
    • Du missachtest komplett die Rule of Five! (https://en.cppreference.com/w/cpp/language/rule_of_three)
      -> Du musst die Move Semantik beachten! (https://en.cppreference.com/w/cpp/language/move_constructor)
    • Warum nutzt du malloc und nicht std::vector?
    • Warum hast du einen Quicksort geschrieben und nutzt nicht std::sort?
    • char iterText[17]; printf(iterText, "I-Werte % 8d", countsOfIter); -> Das ist unter C++ ein völlig veralteter Programmierstil und eine potenzielle Buffer Overflow Sicherheitslücke. Nutze std::format!

    Ein paar Cppcheck Sachen:

    • Apple.cpp Line 127: Common realloc mistake: 'iterMembers' nulled but not freed upon failure
    • Apple.cpp Line 65: '(void*)tmp_x' is of type 'void *'. When using void pointers in calculations, the behaviour is undefined. Arithmetic operations on 'void *' is a GNU C extension, which defines the 'sizeof(void)' to be 1.
    • Apple.cpp Line 182: Member variable '_Apple::xpos' is not initialized in the constructor. Member variables of native types, pointers, or references are left uninitialized when the class is instantiated. That may cause bugs or undefined behavior.
    • _Userinterface.cpp Line 152: Buffer is accessed out of bounds: text
    • _Userinterface.cpp Line 8: When an object of a class is created, the constructors of all member variables are called consecutively in the order the variables are declared, even if you don't explicitly write them to the initialization list. You could avoid assigning 'callback' a value by passing the value to the constructor in the initialization list.

    Das ist jetzt leider für dich ein wenig heftig und das tut mir auch Leid. Aber lerne daraus!

    Vergiss das bisher gelernt und lerne aus einem richtig gutem C++ Buch.

    Ich hab as prog von c in c++ umgeschrieben
    zu Apple.line 127: Wenn ich den Arrays zuvor kein NULL zuweise zeigt es zur Laufzeit Speicherfehler.
    Apple.line 65: Da meckert der Compieler weil er die Größe des Integerwertes nicht kennt, aber das Programm in der thFunc kennt sie
    Apple.line 182: erst nach der Initialisierung durch init() ist die xpos berechnet, und wird zur laufzeit geändert.
    userinterface 152: Da schneidet er die restlichen Stellen einfach ab, oder?
    userinterface line8: Kann ich nicht nachvollziehen, es geschieht doch die Zuweisung im Konstruktor

    Doch danke für deine Hinweise, da hab ich noch ne compilermeldung:
    include/_Colorinterface.cpp:245:86: warning: narrowing conversion of ‘(((_Colorinterface*)this)->_Colorinterface::elements.std::vector<_CiElement>::size() - 1)’ from ‘std::vector<_CiElement>::size_type’ {aka ‘long unsigned int’} to ‘int’ [-Wnarrowing]
    Wenn ich versuche das letzte Objekt im std::vector mit der array.end() "-Funktion" anzusprechen, compiliert er mir nicht.



  • @EL-europ sagte in Klassenfrage 🙂:

    userinterface line8: Kann ich nicht nachvollziehen, es geschieht doch die Zuweisung im Konstruktor

    Die Warnung spricht von der initialization list.



  • @Jockelx
    Ich weiß nicht was genau die Initalisierungsliste bedeuted, aber diese Variable wird zur Laufzeit berechnet und wird public benötigt. Ich hoffe eure Compiler geben nur Hinweise aus das ich auf diese Variable ein Augenmerk haben soll, denn bei mir "meckert" er das nicht an