Array aus Objekten
-
Habe morgen eine Klausur dazu, und habe mich gestern dann daran gemacht zur übung alles mögliche einmal durch zu probieren was ich so für die Klausur vllt wissen muss an Programmier kenntnissen.
Dafür habe ich anfangs ein Struct angelegt(ich steh auf RPGs sei angemerkt):
struct charakter{ string Name; int ID; int LVL; };Und hier der rest der Klasse, warum alles aus kommentiert ist erklär ich dann noch...:
void ausgabe(string &name, int &id, int &lvl){ cout << "#####################\n"; cout << name <<"#\t"; cout << id <<"#\t"; cout << lvl <<"#\t"; cout << "#####################\n"; } void ausgabe(struct charakter* &array){ for(int i=0; i<10; i++){ if(array[i].ID != 0) ausgabe(array[i].Name, array[i].ID, array[i].LVL); } } */ int main(){ struct charakter *array = new charakter[10]; /* while(true){ int i; cout << "Indexposition wählen: "; cin >> i; if(i>=0 && i<=9){ cout << "Name: "; cin >> array[i].Name; //getline(cin, array[i].Name); cout << "ID: " << i+1 << endl; array[i].ID = i+1; cout << "Level: "; cin >> array[i].LVL; ausgabe(array); } else cout << "Eingabe war nicht um Werte Bereich!" << endl; }*/ }Soweit lief alles super
aber das Reicht natürlich nicht, also dachte ich mir, ich erstelle eine KLASSE charakter:#include "charakter.h" using namespace std; void charakter::ausgabe2(string &name, int &id, int &lvl){ cout << "#####################\n"; cout << name <<"#\t"; cout << id <<"#\t"; cout << lvl <<"#\t"; cout << "#####################\n"; } void charakter::ausgabe(struct charakter* &array){ for(int i=0; i<10; i++){ if(array[i].ID != 0) ausgabe2(array[i].Name, array[i].ID, array[i].LVL); } } //getter! string charakter::getName(){ return Name; } int charakter::getId(){ return ID; } int charakter::getLvl(){ return LVL; } //konstruktor charakter::charakter(string Name, int ID, int LVL){ this->Name = Name; this->ID = ID; this->LVL = LVL; } //DEstruktor charakter::~charakter(){ //??? glaube kann jetzt leer bleiben... }darum habe ich auch vieles aus der main auskommentiert, die header datei dazu sieht so aus:
#ifndef CHARAKTER_H #define CHARAKTER_H #include <cstdio> #include <cstdlib> #include <string> #include <iostream> using namespace std; class charakter{ private: string Name; int ID; int LVL; void ausgabe2(string &name,int &id, int &lvl); public: string getName(); int getId(); int getLvl(); void ausgabe(struct charakter* &array); charakter(string Name, int ID, int LVL); ~charakter(); }; #endifsoweit sogut, hab auch ein makefile gemacht, aber ich glaube das interesiert hier nicht so, naja, das problem ist jetzt wie die überschrift vermuten lässt das ich eigendlichgerne ein Array aus den objekten erstellt hätte... aber diese sollen nach bedarf leer bleiben, ich will sie nicht mit werten besetzen, sondern erst wenn man auf das element im array zugreift.
wäre das mit vector gegangen? ist mein ansatz richtig? also kann man das so machen? ich wollte noch gerne etwas mit der vererbung programmieren einen "Protagonisten", aber bevor ich das problem nicht gelöst kriege kann ich mich nicht daran setzen
ich hoffe ihr könnt mir helfen
-
Du suchst wohl std::map. Mit einem array/vector geht das so nicht (und macht auch kaum Sinn), außer du frickelst dir was eigenes hin.
-
Also deine ersten Quellcodestücke sind schonmal nicht Objekt-Orientiert und damit fällt der Begriff "Klasse" weg.
Dann: So wie du die Parameter Übergaben machst ist das absolut nicht schön, gut, üblich oder besonders schnell. (Was zum Teufel ist eine Referenz auf einen Zeiger auf ein 'charakter'? -> "charakter const& c" reicht da)
Die Ausgabe Methode in deiner Klasse ist sinnlos so. Methoden sollten auf den this Daten arbeiten und nicht ausschließlich auf den Parameterdaten so wie bei dir.
Du bietest einen Konstruktor mit 3 Parametern an, dann will der Compiler von dir natürlich, dass du diesen auch benutzt.
Wenn du aber ein Array erstellen willst (wo man keine Konstruktoren aufrufen kann), dann musst du auch einen sogenannten Standardkonstruktor anbieten, dieser hat keine Parameter (was er macht ist deine Sache).
Mit einem Vector würde das gehen:
class charakter // deine Klasse { // ... public: // ... charakter(std::string const& name, int ID, int lvl); //charakter(); wäre der Standard-Kosntruktor }; int main() { std::vector<charakter> chars; charakter c("name", 12, 253); chars.push_back(c); chars.push_back(c); chars.push_back(c); chars.push_back(c); return 0x0; }Ganze einfach...
-
Es ist technisch gesehen möglich, uninitialisierten Speicher zu bekommen und dort gezielt Objekte drin zu erstellen. Aber das ist ganz bestimmt kein Thema deiner Klausur auf deinem Niveau. Das ist eine Spezialität für irgendwelche low-level Hacks. Warum das in normalen Programmen keinen Sinn macht: Was soll denn ein leeres
charaktersein? Wenn es "leer" ist, dann wurde es doch schon erstellt und hat entsprechend einen passenden Konstruktor, um ein "leeres" Objekt zu erstellen (in der Regel signalisiert der Defaultkonstruktor den Standardzustand, den man dann je nach Semantik als "leer" bezeichnen könnte). Deine Klasse hat jedoch (zurecht) keinen Defaultkonstruktor, daher ist gar nicht klar, was hier mit "leer" gemeint sein könnte.Noch 3 Bemerkungen:
1. In C++ machst du immer etwas falsch, wenn du new für Arrays benutzt, vector ist immer die bessere Alternative. ^Ich formuliere diese Aussage bewusst so absolut, irgendein Klugscheißer wird bestimmt gleich irgendeinen Sonderfall an den Haaren herbeiziehen. Hör nicht auf ihn!^
2. Achte mehr auf const-correctness!
3.//DEstruktor charakter::~charakter(){ //??? glaube kann jetzt leer bleiben... }Nein, der kann ganz weg. Der Destruktor wird vom Compiler bei Bedarf automatisch erstellt. Wenn du also keine speziellen Anweisungen im Destruktor hast, dann lass ihn weg. Sonst denkt noch jemand beim Betrachten deiner Klassendefinition, dass da irgendetwas wichtiges im Destruktor passiert, weil du einen eigenen Destruktor deklarierst.
-
Ich seh grad, da du keinen Standard-ctor für charakter hast, funktioniert std::map wohl nicht.
Das problem ist hier etwas ein logisches: Wenn das Objekt noch nicht existiert, brauchst du id/name/level ums zu erstellen, wenn es bereits existiert brauchst du das nicht. Ohne if (...) in irgendeiner form geht das also nicht.
-
wow danke für die schnellen antworten!
also ich fasse mal zsm was ich beim weiter machen beachten soll:
- destruktor fällt weg!
- besser vector als array benutzen!
- ausgabe ist sinnlos so und muss nochmal komplett anders gschrieben werden
- wenn ich ein objekt anlegen will in dem weder name noch ID steht, also nichts, brauche ich den standart konstruktor:charakter::charakter(){}etwa so oder?
-
Einen Konstruktor der nichts tut kannst du einfach weglassen, den generiert der Compiler automatisch wenn du keinen angibst.
Ich würde aber wenigstens ID auf 0 setzen, damit klar ist, dass dieser Character nicht existiert.
-
nwp3 schrieb:
Einen Konstruktor der nichts tut kannst du einfach weglassen, den generiert der Compiler automatisch wenn du keinen angibst.
Jain, der wird vom Compiler generiert, keine Frage, aber auch nur (und genau der Fall ist eignetreten) wenn es keinen anderen Konstruktor gibt (ausser dem Kopierkonstruktor)
-
hm vllt versteh ich dich nur falsch, aber das würde hier keinen sinn machen, vllt hast du auch nur nicht alles gelesen, habe den default construktor schon eingebaut und es stellt mich auch zufrieden soweit.
versuche gerade alles auf vector um zustellen, habe da aber noch nicht soviel erfahrung, weiß nur das es ähnlich wie bei java ist
-
vllt sollte ich mit mal registrieren ^^°
habe folgende fehler meldung wenn ich vector versuche zu benutzen:
main.cpp: In Funktion »int main()«: main.cpp:32:4: Fehler: »vector« ist kein Element von »std« main.cpp:32:25: Fehler: expected primary-expression before »>« token main.cpp:32:27: Fehler: »team« wurde in diesem Gültigkeitsbereich nicht definiertcharakter a("name", 1, 12); vector<charakter> team; team.push_back(a);benutze ich das pushback richtig? warum die fehler meldung =

-
#include <vector>vergessen?
-
achso... entschuldigung ich dachte das gehört zum std... darum war ich verwundert weil ich using namespace std benutze und dann trotzdem ne fehlermeldung kam das es doch nicht dazu gehört...
wie benutzt man das push_back den richtig? gibt es dafür ein anschauliches beispiel vllt?
-
KanakAttack schrieb:
achso... entschuldigung ich dachte das gehört zum std...
Tut es auch.
wie benutzt man das push_back den richtig? gibt es dafür ein anschauliches beispiel vllt?
Ist doch oben schon. Wenn du eine ausführliche Erklärung zu vector möchtest, dann schau in ein C++-Buch deiner Wahl. Die STL ausführlich zu erklären ist zu viel für einen einzelnen Forenbeitrag. Siehe auch hier:
http://www.c-plusplus.net/forum/310212
Und insbesondere hier:
http://magazin.c-plusplus.net/artikel/Aufbau der STL - Teil 1%3A Container
-
Danke nochmal! bin viel weiter schon!
habe jetzt den default konstruktor, den destruktor weg gelassen, und alles läuft entsprechend mit vector... habe jetzt nur ein problem mit der ausgabe:
main.cpp:
#include "charakter.h"
using namespace std;int main(){
string name;
int lvl;
vector<charakter> Team;while(true){
int i;
cout << "Indexposition wählen[0-9]: ";
cin >> i;
if(i>=0 && i<=9){
cout << "Name des Charakters: ";
cin >> name;
cout << "Level des Charakters: ";
cin >> lvl;charakter newChar(name, i+1, lvl);
Team.push_back(newChar);
showChar(newChar);
}
else
cout << "Eingabe war nicht im Wertebereich!" << endl;
}
}charakter.cpp:
#include "charakter.h" using namespace std; void showChar(charakter c){ cout << c.Name << endl; } //getter! string charakter::getName(){ return Name; } int charakter::getId(){ return ID; } int charakter::getLvl(){ return LVL; } //konstruktor charakter::charakter(string Name, int ID, int LVL){ this->Name = Name; this->ID = ID; this->LVL = LVL; } //standart-konstruktor charakter::charakter(){}charakter.h:
#ifndef CHARAKTER_H #define CHARAKTER_H #include <cstdio> #include <cstdlib> #include <string> #include <iostream> #include <vector> using namespace std; class charakter{ private: public: string Name; int ID; int LVL; string getName(); int getId(); int getLvl(); void showChar(charakter c); charakter(string Name, int ID, int LVL); charakter(); }; #endifdas problem liegt bei showChar,

fehlermeldung ist:
main.cpp: In Funktion »int main()«: main.cpp:20:31: Fehler: Elementfunktion »void charakter::showChar(charakter)« kann nicht ohne Objekt aufgerufen werden make: *** [main.o] Fehler 1aber verstehe nicht was sein problem ist...
-
Du musst dich schon entscheiden, ob du eine freie Funktion showCharakter willst,
die einen übergebenen charakter anzeigt oder eine Memberfunktion, die sich selbst anzeigt.Lezteres wäre
public void showChar(); // in main newChar.showChar();
-
ich will aber ersteres
:p
-
- das
using namespace stdhat in Header Dateien nichts zu suchen, das solltest du entfernen
- die Membername, ID, LVLder Klassecharaktersollten privat sein
- um die Member zu initialisieren solltest du Initialisierungslisten benutzen
- der ParameternameimcharakterKonstruktor sollte den Typconst std::string&haben, und nicht per value übergeben werden
- du kannst die lokale VariablenewCharweglassen, indem du den Aufruf direkt in denpush_backAufruf verschiebst:vector<charakter> team; team.push_back( charakter( "Rumpel", i +1, 1 ) );- die Ausgabe hat mMn nichts in der Klasse
charakterzu suchen. EincharakterObjekt sollte nichts von Fenstern oder Konsolen wissen, daher würde ich die Implementierung als freie Funktion vorziehen