Vektor per Schleife mit Klassenobjekten füllen [gelöst]



  • Hallo, ich bin neu hier in der Community, fange gerade mit C++ an und habe eine Frage bezüglich des Befüllens von Vektoren mit Objekten aus einer Klasse. Mein Problem ist, dass ich eine Fehlermeldung erhalte.

    for (int i = 0; i < 10; ++i)
    {
    	ENEMY pers[i];
    	pers[i].AddEnemy(1, 1);
    }
    

    ENEMY ist die Klasse, pers soll das Objekt sein und AddEnemy die Methode. Bezüglich der Zeile … ENEMY pers[i]; … erhalte ich folgende Fehlermeldung für die Zählervariable i :

    Ausdruck wurde nicht zu einer Konstanten ausgewertet bzw. der Ausdruck muss einen Konstantenwert aufweisen.

    Danke für Eure Hilfe!



  • @Kloeterkong sagte in Vektor per Schleife mit Klassenobjekten füllen:

    ENEMY ist die Klasse, pers soll das Objekt sein und AddEnemy die Methode.

    ... und wo ist der std::vector<>??

    @Kloeterkong sagte in Vektor per Schleife mit Klassenobjekten füllen:

    Bezüglich der Zeile … ENEMY pers[i]; … erhalte ich folgende Fehlermeldung für die Zählervariable i:

    Ausdruck wurde nicht zu einer Konstanten ausgewertet bzw. der Ausdruck muss einen Konstantenwert aufweisen.

    Weißt Du was ein Array ist?



  • @Kloeterkong sagte in Vektor per Schleife mit Klassenobjekten füllen:

    ENEMY pers[i];

    Was soll das bedeuten? Der Compiler denkt, du möchtest ein Array von ENEMY anlegen. Das geht aber nur mit einer konstanten Länge und nicht mit einer variablen Länge wie i. Was willst du hier erreichen?



  • Hallo, das geht aber schnell - danke schon einmal für die schnellen Rückinfos. Ich versuche es mal anders zu erklären - habe verstanden das man aus dem Code-Schnipsel nichts erkennen kann - sorry. Hier mal ein Code, welcher 4 Zeilen ausgibt. Einmal über die Darstellungsmethode der Klasse Person, einmal direkt über die Darstellungsmethode der Gruppe:

    #include "pch.h"
    #include <iostream>
    #include <string>
    #include <vector>
    #include <windows.h>

    using std::cout;
    using std::cin;
    using std::string;
    using std::endl;

    class Person
    {
    private:
    string Geschlecht;
    string Name;
    float Abschluss;

    public:
    void add(string name, string geschlecht, float note);
    void ausg();
    };

    class Group
    {
    private:
    std::vector<Person> Gruppe;

    public:
    void addgroup(Person pe);
    void printgroup();
    };

    void Person::add(string name, string geschlecht, float note)
    {
    Geschlecht = geschlecht;
    Name = name;
    Abschluss = note;
    }

    void Group::addgroup(Person pe1)
    {
    Gruppe.push_back(pe1);
    }

    void Group::printgroup()
    {
    for (size_t i = 0; i < Gruppe.size(); ++i)
    {
    Gruppe[i].ausg();
    }
    }

    void Person::ausg()
    {
    cout << "Person: " << Geschlecht << " " << Name << " ,Note: " << Abschluss << endl;
    }

    int main()
    {
    Person pers1;
    Person pers2;
    Group gruppe1;

    pers1.add("Max", "Mustermann", 2.0);
    pers1.ausg();
    pers2.add("Hans", "Meier", 2.2);
    pers2.ausg();

    gruppe1.addgroup(pers1);
    gruppe1.addgroup(pers2);
    gruppe1.printgroup();

    Sleep(100000);

    }

    Mein Ziel soll sein, dass ich die Objekte des Verktors gerne über eine Schleife einlesen lasse und nicht wie im Beispiel explizit mit pers1, pers2 oder gruppe1 … deswegen die Idee mit der Schleife.



  • Ich sehe gerade, der Quelltext ist nicht formatiert, da arbeite ich natürlich dran wenn ich sowas hier hereinstelle, danke fürs Verständnis 😐



  • Formatieren geht mit ``` vor und nach deinem Code oder mit dem </>-Button.



  • Dann nochmal anständig …

    #include "pch.h"
    #include <iostream>
    #include <string>
    #include <vector>
    #include <windows.h>
    
    using std::cout;
    using std::cin;
    using std::string;
    using std::endl;
    
    class Person
    {
    private:
    	string Geschlecht;
    	string Name;
    	float Abschluss;
    
    public:
    	void add(string name, string geschlecht, float note);
    	void ausg();
    };
    
    class Group
    {
    private:
    	std::vector<Person> Gruppe;
    
    public:
    	void addgroup(Person pe);
    	void printgroup();
    };
    
    void Person::add(string name, string geschlecht, float note)
    {
    	Geschlecht = geschlecht;
    	Name = name;
    	Abschluss = note;
    }
    
    void Group::addgroup(Person pe1)
    {
    	Gruppe.push_back(pe1);
    }
    
    void Group::printgroup()
    {
    	for (size_t i = 0; i < Gruppe.size(); ++i)
    	{
    		Gruppe[i].ausg();
    	}
    }
    
    void Person::ausg()
    {
    	cout << "Person: " << Geschlecht << " " << Name << " ,Note: " << Abschluss << endl;
    }
    
    int main()
    {
    	Person pers1;
    	Person pers2;
    	Group gruppe1;
    
    	pers1.add("Max", "Mustermann", 2.0);
    	pers1.ausg();
    	pers2.add("Hans", "Meier", 2.2);
    	pers2.ausg();
    
    	gruppe1.addgroup(pers1);
    	gruppe1.addgroup(pers2);
    	gruppe1.printgroup();
    
    	Sleep(100000);
    
    } 
    
    


  • Also erstmal verwirrt dein Naming. Wenn du von einer Personen den Namen setzt, nennst du das "add"?! Add heiß hinzufügen/addieren. Dein add setzt aber die Daten.

    Bei der Gruppe ähnlich. addgroup fügt nicht eine Gruppe hinzu, sondern eine Person. Nenne es doch addperson. Oder lass deine Gruppenklasse ganz weg, es handelt sich doch eigentlich nur um einen std::vector<Person>.

    Wenn du in einer Schleife der Gruppe n Personen hinzufügen willst, dann:

    for (auto i = 0; i < 10; ++i) {
        Person p;
        gruppe1.addgroup(p);
    }
    

    Aber beachte meinen Kommentar zum verwirrenden Namen addgroup.

    Edit: du kannst deinen ersten Beitrag auch bearbeiten über die drei Punkte rechts neben dem "Zitieren"-Link.



  • Noch 3 Kommentare:

    1. willst du wirklich die vielen using... nutzen? Ich würde eher davon abraten.
    2. Das hier:
    for (size_t i = 0; i < Gruppe.size(); ++i)
     	{
     		Gruppe[i].ausg();
     	}
    

    kannst du besser schreiben:

    for (const auto &person : gruppe) {
        person.ausg();
    }
    

    Beachte insbesondere, dass du hier keinen Zähler i brauchst, wenn du über alle Elemente loopen willst. Das ist weniger fehleranfällig und leichter lesbar.
    Statt "Für alle Zahlen i von 0 bis einen weniger als Gruppenlänge mach XY" liest sich das als "Für jede Person person aus der Gruppe mach XY".

    1. Du scheinst allgemein weder const noch Referenzen const & zu nutzen. Kommt vielleicht noch später beim Lernen. Aktuell erzeugst du relativ viele Kopien, die vermeidbar wären.

    2. (von 3 ;-)) allgemein nutzt man den operator<< für die Ausgabe statt einer ausg()-Funktion. Aber da du bestimmt noch nicht weißt, wie das geht, ist das auch ne Info für später.

    3. Ich würde dir noch raten, Variablen und Funktionen mit Kleinbuchstaben und Klassen mit Großbuchstaben zu beginnen. Also Gruppe sollte eine Klasse sein, während gruppe die Variable wäre.

    4. Und das Deutsch/Englisch-Gemisch macht es nicht besser. Du hast eine Klasse Group und eine Variable Gruppe. Entscheide dich für eine Sprache (Englisch, wenn möglich - nur wenn es mal irgendwelche Spezialbegriffe aus dem Anwendungsbereich gibt, die es so nicht direkt in EN gibt, kann man einzelne deutschsprachige Namen behalten).



  • Danke, jetzt habe ich es so einigermaßen kapiert und klappt jetzt auch. Die using´s habe ich durch using namespace std; ersetzt und ich hoffe das mit const und const & kommt noch, genauso wie der sichere Umgang mit Namenskoventionen 🙂 … wenn man sowas im Selbststudium und dicken Wälzern neben sich versucht zu lernen verzweifelt man ab und an …. positiver Effekt allerdings, man vertieft das, was man schon kann, auch wenn es noch sehr wenig ist ☺ …. aber Übung macht ja bekanntlich den Meister ...

    Vielen Dank!!!!


  • Mod

    Ich habe ja jede Menge Abschlüsse, aber noch keinen davon konnte ich als float ausdrücken...

    (Oder die Moral dahinter: Wenn man stets versucht, alles möglichst perfekt zu modellieren - auch und gerade den einfachen Kinderkram - dann fallen einem später die schwierigen Datenmodelle viel leichter)



  • Hallo, das ist jetzt meine Anfänger-Lösung 🙂 ….

    	srand((unsigned)time(NULL)); // Zufallsgenerator initialisieren.
    
    	for (auto z = 0; z < 30; ++z) 
    	{
    	int zufall1 = rand() % 120 + 1;
    	int zufall2 = rand() % 30 + 1;
    	int zufall3 = rand() % 100 + 1;
    	ENEMY Gegner("Gnom", zufall1, zufall2, zufall3);   
    	Armee.push_back(Gegner);
    	}
    

    Das Objekt Gegner der Klasse ENEMY erhält bei der Erstellung bereits über den Konstruktor gewisse Eigenschaften. Armee ist der Vektor.

    DANKE für Eure Hilfen und Hinweise!

    Gegen Verbesserungsvorschläge habe ich natürlich nichts 🙂 ...



  • @Kloeterkong

    for (auto z = 0; z < 30; ++z) 
    {
    	int zufall1 = rand() % 120 + 1;
    	int zufall2 = rand() % 30 + 1;
    	int zufall3 = rand() % 100 + 1;
    	Armee.emplace_back( "Gnom", zufall1, zufall2, zufall3 );
    }
    

    Mit "emplace_back" hast du den Vorteil, dass das Objekt vom Typ "ENEMY" direkt im vector erzeugt wird, anstatt es erst zu erzeugen und dann zu kopieren. Du übergibst einfach nur die Konstruktor-Parameter an die "emplace_back"-Funktion.

    Weitere Verbesserungsvorschläge:

    • aussagekräftigere Variablennamen als "Zufall1", etc.
    • bei Zählschleifen kann man sich ruhig eine nrichtigen Typ gönnen, anstatt es durch "auto" zu erschlagen. In deinem Fall verwendest du "z" nicht weiter, daher ist es egal, aber ich finde es persönlich besser, in dem Fall eben z.B. "unsigned" zu verwenden, wenn du nur im positiven ganzzahligen Bereich arbeitest.
    • Die oberen Grenzwerte für deine Zufallszahlen ( 120, 30, 100 ) könntest du in Konstanten packen, die aussagekräftige Namen haben. Z.B. "MaxDexterity" oder, was auch immer die bedeuten.


  • @Kloeterkong sagte in Vektor per Schleife mit Klassenobjekten füllen [gelöst]:

    Gegen Verbesserungsvorschläge habe ich natürlich nichts

    Geschlecht sollte kein string sein, sondern ein enum. Du hast eine public Methode 'add' wo jeder bei Geschlecht eintragen kann was er will ('Mann', 'männlich' 'm',...).
    Wenn du dann z.B. mal alle Männer finden sollst, hast du direkt ein Problem.


  • Mod

    @Jockelx sagte in Vektor per Schleife mit Klassenobjekten füllen [gelöst]:

    @Kloeterkong sagte in Vektor per Schleife mit Klassenobjekten füllen [gelöst]:

    Gegen Verbesserungsvorschläge habe ich natürlich nichts

    Geschlecht sollte kein string sein, sondern ein enum. Du hast eine public Methode 'add' wo jeder bei Geschlecht eintragen kann was er will ('Mann', 'männlich' 'm',...).
    Wenn du dann z.B. mal alle Männer finden sollst, hast du direkt ein Problem.

    Noch besser wäre, gar keine festen Attribute zu haben, sondern eine flexible Liste von Attributbeschreibungen und zugehörigen Werten. Nicht jede Person auf der Welt wird über die gleichen Attribute beschrieben; hat alle Attribute, die du für wichtig hältst; oder du kennst nicht alle ihre Attribute.

    Attribut Wert
    Vorname Max
    Nachname Mustermann
    Lieblingsfarbe blau
    Anzahl Finger 9

    Das ist aber ziemlich philosophisch zur Datenmodellierung und hilft dir weniger beim Erlernen von C++.



  • @Jockelx sagte in Vektor per Schleife mit Klassenobjekten füllen [gelöst]:

    Geschlecht sollte kein string sein, sondern ein enum.

    Oha. Darf man sowas heutzutage noch vorschlagen, ohne dafür einen Shitstorm zu ernten? Was, wenn du ein Geschlecht vergessen hast? Oder willst du ein enum { w, m, d, andere, keineAngabe } machen? Wahrscheinlich würde ich versuchen, auf dieses Attribut zu verzichten. Einfach weil es nur Ärger macht. Irgendjemand, und wenn es nur ein Kolleg*in ist, der/die den Code liest, wird sich beleidigt fühlen.


  • Mod

    @wob sagte in Vektor per Schleife mit Klassenobjekten füllen [gelöst]:

    @Jockelx sagte in Vektor per Schleife mit Klassenobjekten füllen [gelöst]:

    Geschlecht sollte kein string sein, sondern ein enum.

    Oha. Darf man sowas heutzutage noch vorschlagen, ohne dafür einen Shitstorm zu ernten? Was, wenn du ein Geschlecht vergessen hast? Oder willst du ein enum { w, m, d, andere, keineAngabe } machen? Wahrscheinlich würde ich versuchen, auf dieses Attribut zu verzichten. Einfach weil es nur Ärger macht. Irgendjemand, und wenn es nur ein Kolleg*in ist, der/die den Code liest, wird sich beleidigt fühlen.

    Das ist Anwendungsspezifisch.

    • Die Mitgliederliste deines Buchclubs: Warum fragst du überhaupt?
    • Deine Wahlumfrage: Wichtiges Gruppierungskriterium, das nicht fehlen darf, und wo es hauptsächlich auf die Selbstwahrnehmung des Befragten ankommt.
    • Deine medizinische Humanstudie zur Wirkung eines neuen Medikaments: Frag gar nicht erst, sondern nimm gleich eine Blutprobe.


  • @wob sagte in Vektor per Schleife mit Klassenobjekten füllen [gelöst]:

    Oha. Darf man sowas heutzutage noch vorschlagen, ohne dafür einen Shitstorm zu ernten?

    Sicher darf man das.
    Ich kann mich nicht erinnern mich jemals irgendwo registriert (oder was auch immer) zu haben und bei "Geschlecht" dann keine Combobox, sondern Freitext ausfüllen zu müssen.



  • @wob sagte in Vektor per Schleife mit Klassenobjekten füllen [gelöst]:

    @Jockelx sagte in Vektor per Schleife mit Klassenobjekten füllen [gelöst]:

    Geschlecht sollte kein string sein, sondern ein enum.

    Oha. Darf man sowas heutzutage noch vorschlagen, ohne dafür einen Shitstorm zu ernten? Was, wenn du ein Geschlecht vergessen hast? Oder willst du ein enum { w, m, d, andere, keineAngabe } machen? Wahrscheinlich würde ich versuchen, auf dieses Attribut zu verzichten. Einfach weil es nur Ärger macht. Irgendjemand, und wenn es nur ein Kolleg*in ist, der/die den Code liest, wird sich beleidigt fühlen.

    Unerheblich wer sich beleidigt fühlt. Rein rechtlich ist glaube "männlich, weiblich, diverse" absolut in Ordnung. Meine ich mal gelesen zu haben. Und nur die Rechtslage ist maßgeblich. Und das lässt sich prima durch ein enum erschlagen.


Log in to reply