Klassen



  • Habe mir jetzt mal Klassen angeschaut, leider geht aus dem Buch das nicht klar hervor.

    Muss ich Klassen in der main() Funktion definieren?
    Vielleicht ne dumme Frage, aber bei den andere Programmiersprachen / Skriptsprachen ist dies bisschen anders.



  • Gozyu schrieb:

    Muss ich Klassen in der main() Funktion definieren?

    Nein, obwohl das auch möglich ist und manchmal (selten) gemacht wird. Klassen werden normalerweise ausserhalb jeder Funktion definiert. In der Regel in einer eigenen Headerdatei.



  • nein.

    üblicherweise definiert man klassen in einer headerdatei
    die implementierungen der methoden in einem cpp file
    und die main in einem weiteren cpp file.



  • Ok, danke für eure Antworten. Hab gleich neue Fragen:
    1. Wenn ich eine Objekt einer Klasse erstellen

    Cat Frisky;
    

    Wie kann ich machen, dass bestimmte Eigenschaften, dann automatisch gesetzt werden (Standartwerte), ohne dass ich was übergeben muss?

    2. Kann ich dynamisch neue Objekte in einer Klasse erstellen, also dass ich nicht im Code schreiben muss:

    Cat Frisky;
    

    Sondern im Konsolenfenster sowas zum Beispiel
    Mache Cat Frisky //Objekt Frisky in der Klasse Cat erstellen



  • Gozyu schrieb:

    Cat Frisky;
    

    Wie kann ich machen, dass bestimmte Eigenschaften, dann automatisch gesetzt werden (Standartwerte), ohne dass ich was übergeben muss?

    Im Konstruktor der Klasse.

    2. Kann ich dynamisch neue Objekte in einer Klasse erstellen, also dass ich nicht im Code schreiben muss:

    Cat Frisky;
    

    Sondern im Konsolenfenster sowas zum Beispiel
    Mache Cat Frisky //Objekt Frisky in der Klasse Cat erstellen

    Mit dem new-Operator. Wahrscheinlich wird dir das nichts sagen, warte einfach ab, bis es in deinem Buch kommt (C++ in 21 Tagen oder sowas in der Richtung ist das doch?)



  • Standardwerte kannst du im Konstruktor setzen. Dynamisch erzeugst du Objekte mit new auf dem Heap. Sollte alles in einem gute Buch oder Tutorial (von Shade oder volkard) drin stehen. Die Konsoleneingaben musst du parsen und auswerten bevor das Programm damit etwas anfangen kann.



  • Noch ein Tip: Schmeiss dein Buch weg und kauf dir ein gutes, dass was du hasst ist auf gut Deutsch beschxxxxx! 👎



  • Ich habe das genommen, dass hier gerade rumstand, es heisst:
    Jetzt lerne ich C++ und ist von Markt und Technik. Besseres Buch habe dann erst ab Freitag.

    Also habe das Klassenkapitel durch und weiss jetzt immer noch nicht wie ich dynamische Objektnamen machen kann.
    New und Heap sagt mir leider nicht gerade viel, kann mir einer ein Codebeispiel liefern?



  • Cat *pcat;
    // ...
    pcat = new Cat;
    // ...
    delete pcat; // nicht vergessen
    

    Nur als Idee. Das entscheidende ist, dass du das Objekt erst dann erzeugst, wenn du den new-Ausdruck auswertest. Das kann also durch Benutzereingaben oder andere Entscheidungen gesteuert werden. Weiterhin lebt das Objekt so lange, bis der delete-Operator auf den Zeiger aufgerufen wird, anstatt am Ende des Blockes automatisch zerstört zu werden. Natürlich musst du darauf achten, dass du den Zeiger nicht verlierst, da das Objekt dann zur "ewigen Schattenexistenz" verdammt ist.

    Du kannst auf diese Weise beliebig viele Cat-Objekte erstellen und ihre Zeiger irgendwo speichern (Array, vector, Liste, etc.). Was du nicht kannst, ist analog zu "Cat frisky;" einen Variablennamen dynamisch erstellen. Das wär auch nicht besonders sinnvoll, weil du darauf im restlichen Programm ja auch wieder nur über einen dynamischen Variablennamen zugreifen könntest. Scriptsprachen wie Perl oder Python realisieren intern alle Variablen über assoziative Arrays, wodurch solche Sachen möglich sind. Am nächsten kommt dem in C++ der assoziative Container map. Beispiel:

    #include <map>
    #include <string>
    using namespace std;
    int main() {
      map<string, Cat*> katzen;
      ...
      string name;
      cout << "Katzenname: ";
      cin >> name;
      katzen[name] = new Cat; // anlegen
      ...
       // zugreifen
      katzen["Frisky"]->meow();
      ...
      // Katzen töten
      for (map<string, Cat*>::iterator iter = katzen.begin(); iter != katzen.end(); ++iter)
        delete iter->second;
    }
    

    Ich kann wahrscheinlich davon ausgehen, dass du damit nicht viel anfangen kannst, aber du wolltest es wissen 🤡



  • Bashar schrieb:

    #include <map>
    #include <string>
    using namespace std;
    int main() {
      map<string, Cat*> katzen;
      ...
      string name;
      cout << "Katzenname: ";
      cin >> name;
      katzen[name] = new Cat; // anlegen
      ...
       // zugreifen
      katzen["Frisky"]->meow();
      ...
      // Katzen töten
      for (map<string, Cat*>::iterator iter = katzen.begin(); iter != katzen.end(); ++iter)
        delete iter->second;
    }
    

    <insider>wo ist der hund?</insider>



  • Zum Glück ist C++ nur virtuell grausam.



  • den unteren Code verstehe ich bis auf das Katzen töten, aber das Grundprinzip ist mir leider nicht klar.
    Falls ich jetzt die Objekte einfach durchnummeriere, und ihr Name einfach eine Eigenschaft ist, muss ich den obigen Code verwenden oder?

    Cat *pcat;
    

    Was bewirkt das jetzt genau?

    Wenn ich eine neue Katze erstellen will, muss ich dann in einer Funktion tun, nehme ich an.



  • Gozyu schrieb:

    den unteren Code verstehe ich bis auf das Katzen töten

    mit "töten" meine ich einfach, die in der map gespeicherten Objekte zu zerstören. Jedes Objekt hat eine Lebenszeit. Du wirst schon mit Objekten mit automatischer Lebensdauer gearbeitet haben:

    int main() {
      Cat frisky;  // frisky beginnt zu existieren
      // ...
    } // Block-Ende: frisky wird zerstört
    

    Objekte die mit new auf dem Freispeicher angelegt werden, haben eine dynamische Lebensdauer, die nicht durch die Blockstruktur des Programms vorgegeben ist. Deshalb müssen sie von Hand zerstört werden ... mit Hilfe des delete-Operators, wie im Beispielprogramm.

    aber das Grundprinzip ist mir leider nicht klar.
    Falls ich jetzt die Objekte einfach durchnummeriere, und ihr Name einfach eine Eigenschaft ist, muss ich den obigen Code verwenden oder?

    Ich bin mir nicht sicher, ob ich verstehe, wovon du sprichst. Du meinst, du willst ein Array von Katzen haben? Dann sind sie durchnummeriert ...

    Cat katzen[10]; // erzeugt 10 Katzen auf einmal
    ...
    katzen[7].meow(); // Zugriff auf Katze Nr. 7 (Zählung von 0 bis 9)
    

    Oder haben die Katzen einen Konstruktor, mit dem man ihre Namen festlegen kann? Dann nimm ein Array von Zeigern:

    Cat *katzen[10];
    for (int i = 0; i < 10; ++i)
    {
      string name;
      cout << "Katze Nr. " << i  << " soll wie heißen? :";
      cin >> name;
      katzen[i] = new Cat(name);
    }
    ...
    for (int i = 0; i < 10; ++i)
      delete katzen[i];
    

    Oder irgendeine andere Containerklasse (vector z.B.).

    Cat *pcat;
    

    Was bewirkt das jetzt genau?

    Das definiert eine Variable vom Typ "Zeiger auf Cat". Ein Zeiger repräsentiert den Speicherort eines Objektes (die Adresse). Da der new-Operator die Adresse eines neu angelegten dynamischen Objektes zurückgibt, verwendet man Zeiger unter anderem, um mit dynamischen Objekten umzugehen.

    BTW ich hab eigentlich nicht vor, dir das Lesen des Buches zu ersparen.


Log in to reply