Allgemeine Frage zu Klassen



  • Hi Leute.
    Ich habe mal eine Verständnisfrage zu Klassen.
    Egal welches Buch man sich kauft, wenn es um Klassen geht, wird einem kurz die OOP erklärt und dann werden als Beispielklassen immer wieder Tiere, Menschen, Autos, Fahrräder oder ähnliches genannt.
    Das erklärt die OOP recht gut, ist aber nicht wirklich hilfreich, wenn man selbst mal etwas schreiben möchte und sich überlegt, ob man hier oder da nicht vielleicht auf eine Klasse zurückgreifen sollte.

    Wenn ich bspw. ein Spiel programmieren will, (Ich bin Lichtjahre davon entfernt) dann machen Klassen für mich Sinn, denn in dem oder dem Buch habe ich ja gelesen, wie man "Menschen" erzeugt 😅
    Ich erstelle eine Klasse "Spieler" und weil ich ja nicht allein spielen will, erstelle ich noch viele weitere Instanzen.
    Ok, habs verstanden 😁

    Aber wo kommen Klassen noch zum Einsatz, bzw. wo macht es Sinn?
    und macht es hier und da überhaupt Sinn?
    Ich habe zum Beispiel mal ein Youtube Video gesehen, wo jemand "TicTacToe" programmiert hat und eine Klasse "Spielfeld" erstellt hat.

    Für mich hat das erstmal keinen Sinn ergeben, denn ich habe ja immer wieder gelesen, das man Klassen nutzt um schnell viele Instanzen von einem Objekt zu erstellen. Dann steht in jedem Buch auch noch was von Vererbung und Polymorphie etc. was dazu führte, dass ich noch weniger nachvollziehen konnte, wieso er gerade eine Klasse geschrieben hat, um dieses Spielfeld nur ein einziges Mal zu erzeugen. Welchen Vorteil hat es dann in dem Zusammenhang, eine Klasse zu nutzen?

    Wäre super, wenn ihr mir mal kurz und verständlich erklärt, was ich hier nicht verstanden habe.
    Ich habe eine riesen Knoten im Knopf was dieses Thema angeht und möchte es endlich verstehen, denn ich will weder Menschen, noch einen Zoo oder Hunde verschiedener Rassen programmieren 😄
    Danke euch



  • Klassen haben nur Bedingt damit zu tun dass man mehrere Instanzen/Objekte erstellt. Das geht damit schön. Geht aber ohne OOP auch. Das ist kein entscheidendes Merkmal für OOP.

    Primär wichtig bei OOP ist es Daten und Code der mit diesen Daten arbeitet zusammenzufassen. Stichwort Kapselung.

    Stell dir vor du hast eine Firma. Die Firma besteht aus Dingen, Mitarbeitern und hoffentlich einer guten Definition von Vorgängen (also wie bestimmte Dinge erledigt werden).

    Angenommen es kommt jetzt ein Kunde der von der Firma etwas möchte. Und vergessen wir mal vorsätzlichen Betrug - wir gehen davon aus dass der Kunde niemanden bescheissen oder beklauen möchte.

    Trotzdem wäre es blöd wenn der Kunde einfach in die Firma reinspazieren könnte, sich ein paar Werkzeuge und Rohstoffe schnappen, damit irgendwas bauen, und dann den Betrag den er meint schuldig zu sein an dem Ort ablegt wo er meint dass das Geld halt hingehört.
    Das würde nicht lange gut gehen.

    Deswegen erlaubt man das nicht. "Zugriff" auf die Firma ist nur über bestimmte, definierte Wege möglich. Also vielleicht hat die Firma eine Webseite wo man was bestellen kann. Oder man kann anrufen und einen Auftrag durchgeben. Oder auch vor Ort vorbeischauen und mit einem Mitarbeiter reden.

    Bei der Programmierung ist es nicht anders. Analog zur Firma gibt es hier ein Objekt. Das Objekt besteht aus Daten und definierten Vorgängen wie mit diesen Daten gearbeitet wird ("Methoden", "Memberfunktionen"). Auch hier möchte man nicht dass jeder Programmteil direkt in den Daten des Objekts ändern kann was er möchte. Zugriffe auf das Objekt erlaubt man nur über genau definierte Wege.

    Und genau so wie eine einzelne Firma sinnvoll sein kann (man muss nicht immer 100e Filialen/Standorte haben) ist es bei Programmen auch: oft braucht man nur ein Objekt. Das Objekt hat einen Bauplan (die Klasse) mit dem man weitere Objekte bauen könnte. Aber wenn man nur eins braucht dann baut man halt nur eins.

    Den Vorteil dass alles geordnet abläuft hat man trotzdem.

    Die Kunden des Objekts wären in diesem Vergleich dann andere Programmteile die andere Teilaufgaben übernehmen.


    Die ganzen Sachen wie Polymorphie und Vererbung sind dann erweiterte Konzepte. Aber auch hier ist es nicht immer nötig mehrere Objekte zu haben damit das Sinn macht. Angenommen ich möchte nicht Tic-Tac-Toe spielen sondern eine Spiel wo man mit einem Auto, Motorrad oder Luftkissenboot rumfahren kann. Es gibt pro Runde nur einen Spieler und nur ein Fortbewegungsmittel. Die drei Fortbewegungsmittel verhalten sich unterschiedlich. Die Steuerung ist aber in allen Fällen identisch - sagen wir mal über die Cursortasten. Weiters haben alle Fortbewegungsmittel gemeinsam dass man sie zeichnen kann, dass man für jede Stelle des Spielfelds prüfen kann ob man da hinfahren kann oder nicht etc. Das Ergebnis des Zeichnens/der Überprüfung mag unterschiedlich sein -- aber die Aufrufe sehen gleich aus.

    Dann kann ich eine Klasse Fortbewegungsmittel basteln, und davon 3 weitere ableiten - eine für's Auto, eine fürs Motorrad und eine für's Luftkissenboot. Je nachdem was der Spieler auswählt erstelle ich dann genau ein Objekt der passenden Klasse.

    Und das restliche Spiel kann dieses Objekt dann einfach als Fortbewegungsmittel verwenden. Eine Unterscheidung anhand dessen ob der Spieler nun das Auto, das Motorrad oder das Luftkissenboot ausgewählt hat ist dort nicht mehr notwendig. Auch das macht also Sinn selbst wenn man nur ein Objekt erstellt.



  • @hustbaer Klasse!



  • Danke 🙂
    Bin schon froh wenn's besser als ne Wurstsemmel ist 😃



  • @hustbaer Ich habe reflexartig sofort nach "Supermarkt" gesucht ^^



  • Wo kommt das eigentlich her? Hab's vergessen.



  • @hustbaer hat es schon gut erklärt. Aber um nochmal zu deinem Spiel mit einem Spielfeld zurückzukommen: warum brauchst du nur eins? Stell dir vor, du möchtest das Spiel nun als Netzwerkspiel für hunderte User anbieten - je 2 davon brauchen ein Spielfeld. Du kannst nun einfach anzahlSpieler/2 Spielfelder erzeugen und fertig.

    Außerdem kannst du nach jedem Zug das Spielfeld kopieren, damit die Spieler nach Spielende nochmal zurück zu einem Spielstand gehen können und sich ihre Fehler oder genialen Züge anschauen können.

    Vielleicht willst du ein Spiel auch speichern und ein neues Spiel starten und dann zwischen den Spielen wechseln. Schon brauchst du mehrere Spielfelder.

    Zur Polymorphie: ich benutze eigentlich nur sehr selten Polymorphie. Die ist nämlich nicht immer die beste Lösung. Hängt sicher von den Problemem ab, die man so bearbeitet. Oder anders gesagt: benutzt nicht auf Zwang Polymorphie. (sondern nur da, wo wirklich sinnvoll)



  • @hustbaer sagte in Allgemeine Frage zu Klassen:

    Wo kommt das eigentlich her? Hab's vergessen.

    Jürgen Wolf - C++ von A bis Z Das umfassende Handbuch, 2. aktualisierte Auflage 2009, S. 468

    https://abload.de/img/wolff4jl6.png

    Hier der ungekürzte Unfall:

    // mehrfachvererb3.cpp
    #include <iostream>
    #include <cstring>
    using namespace std;
    
    class Supermarkt {
    protected:
        char markt[100];
    public:
        Supermarkt(const char* m = "") {
            strncpy(markt, m, 100);
            markt[100 - 1] = 0;
        }
        ~Supermarkt() {}
        const char* get_markt() const { return markt; }
    };
    
    class Brot : public Supermarkt {
    protected:
        char brot[100];
        unsigned int gramm;
    public:
        Brot(const char* b = "", unsigned int g = 0,
            const char* m = "") : Supermarkt(m) {
            strncpy(brot, b, 100);
            brot[100 - 1] = 0;
            gramm = g;
        };
        ~Brot() {}
        unsigned int get_gramm() const { return gramm; };
        const char* get_brot() const { return brot; };
    };
    
    class Wurst : public Supermarkt {
    protected:
        char wurst[100];
        unsigned int gramm;
    public:
        Wurst(const char* w = "", unsigned int g = 0,
            const char* m = "") : Supermarkt(m) {
            strncpy(wurst, w, 100);
            wurst[100 - 1] = 0;
            gramm = g;
        };
        ~Wurst() {}
        unsigned int get_gramm() const { return gramm; };
        const char* get_wurst() const { return wurst; };
    };
    
    class Wurstbrot : public Brot, public Wurst {
    public:
        Wurstbrot(const char* b, unsigned int g1, const char* s1,
            const char* w, unsigned int g2, const char* s2) :
            Brot(b, g1, s1), Wurst(w, g2, s2) { }
        ~Wurstbrot() {}
        void get_All() const {
            cout << "Gramm : " << Brot::get_gramm() << '\n';
            cout << "Brot : " << get_brot() << '\n';
            cout << "Gekauft bei : " << Brot::get_markt() << '\n';
            cout << "Gramm : " << Wurst::get_gramm()
                << '\n';
            cout << "Wurst : " << get_wurst() << '\n';
            cout << "Gekauft bei : " << Wurst::get_markt()
                << '\n';
        }
    };
    
    int main() {
        Wurstbrot wbrot("Vollkornbrot", 100, "Meier",
            "Salami", 3, "Eberhardt");
        cout << "Gramm : " << wbrot.Brot::get_gramm()
            << '\n';
        cout << "Brot : " << wbrot.get_brot() << '\n';
        cout << "Gekauft bei : " << wbrot.Brot::get_markt()
            << '\n';
        cout << "Gramm : " << wbrot.Wurst::get_gramm()
            << '\n';
        cout << "Wurst : " << wbrot.get_wurst() << '\n';
        cout << "Gekauft bei : " << wbrot.Wurst::get_markt()
            << '\n';
        cout << '\n';
        // ... oder alle auf einmal
        wbrot.get_All();
        return 0;
    }
    


  • @wob sagte in Allgemeine Frage zu Klassen:

    Zur Polymorphie: ich benutze eigentlich nur sehr selten Polymorphie. Die ist nämlich nicht immer die beste Lösung. Hängt sicher von den Problemem ab, die man so bearbeitet. Oder anders gesagt: benutzt nicht auf Zwang Polymorphie. (sondern nur da, wo wirklich sinnvoll)

    Dem möchte ich mich anschliessen. Mehr oder weniger 🙂

    Denn ... Polymorphie ist oft schon ganz gut. Stichwort Testbarkeit. Was man mMn. eher vermeiden sollte ist Vererbung. Abgesehen von reiner Interface-Vererbung, die in Sprachen wie C++ das Mittel der Wahl ist um Polymorphie umzusetzen.

    Was aber sicherlich stimmt ist dass es keinen Sinn macht Polymorphie zum Selbstzweck irgendwo draufzuwerfen.



  • @Swordfish Ah, Wurstbrot und nicht Wurstsemmel. Deswegen war mit Google kaum was zu finden.



  • Ein Wurstbrot ist ein Supermarkt?! WTF!



  • @wob Frag' Jürgen 🤷♂



  • @Swordfish sagte in Allgemeine Frage zu Klassen:

    Hier der ungekürzte Unfall:

    ROFL 🤣



  • @robert123 sagte in Allgemeine Frage zu Klassen:

    Egal welches Buch man sich kauft

    Welche hast du denn gekauft?



  • Alles klar.
    Vielen Dank.
    Vielleicht sollte ich einfach mal anfangen Klassen zu benutzen, dann wird sicher einiges klarer.
    Bis jetzt löse ich alles über normale Funktionen etc.
    Danke euch.

    Und was das Wurstbrot angeht, schaue ich doch direkt mal ins Buch.
    Das habe ich nämlich auch hier 😂



  • @manni66
    An Büchern habe ich:

    • Das oben angesprochene von Jürgen Wolff
    • Einführung in die programmierung mit c++ (Pearson) von Bjarne S.
    • C++ Primer
    • Intensivkurs C++: Schneller Einstieg über die Standardbibliothek

    Wobei letzteres eher für etwas fortgeschrittenerer User ist, das habe ich aber erst gemerkt als ich es gekauft habe.
    Ich habe die Bücher noch nicht durch und hole sie immer mal wieder aus dem Schrank.
    Ist sicher der falsche Weg in das Thema einzusteigen, da man eigentlich nie wirklich voran kommt und Fertig schon mal garnicht.
    Aber das Thema interessiert mich doch schon ziemlich, aber mir fehlt auch etwas die Zeit es wirklich durchzuziehen.
    Wobei ich sagen muss, dass ich mich in letzter Zeit doch schon intensiver damit beschäftige als noch vor einiger Zeit.
    Hinzu kommt auch dass ich Tatsächlich vor kurzem mein erstes richtiges Programm geschrieben habe und es auch noch funktioniert. Da war ich schon etwas stolz auf mich. 😊



  • Das oben genannte kannst direkt wegwerfen.



  • Jürgen Wolff?
    Warum?
    Und generell-
    Wie kann man ein gutes von einem schlechten unterscheiden?



  • https://www.c-plusplus.net/forum/topic/272350/warnung-bücher-von-jürgen-wolf-zu-c-und-c-zum-lernen-ungeeignet-weil/26

    @robert123 sagte in Allgemeine Frage zu Klassen:

    Wie kann man ein gutes von einem schlechten unterscheiden?

    Kannst du als anfaenger nicht.
    Sowohl hier, als auch auf stackoverflow gibt es buecher listen.



  • @robert123 sagte in Allgemeine Frage zu Klassen:

    Warum?

    Weil der Autor selbst keine Ahnung hat.


Anmelden zum Antworten