Dynamische Anzahl von Istanzen einer Klasse anlegen.
-
Hallo zusammen, ich habe mal eine Frage:
Ich möchte gerne eine dynamische Anzahl von Instanzen einer Klasse anlegen ich bekomme nun einen Speicherfehler, da ich vermute, dass der Standardkonstuktor aufgerufen wird, der aber noch keinen Speicher für die Variablen der Klasse reserviert hat.
Hat jemand eine Idee wie ich das Problem lösen kann?
Hier mal der Code:
#include <iostream> #include <iomanip> #include <conio.h> #include <string> using namespace std; // Klassendefinition class Student { private: //Variablen deklarieren string *sMatrikel; string *sVorname; string *sNachname; string *sStudiengang; int *iAlter; public: //Funktionen deklarieren Student( const char *const sV, const char *const sN, const char *const sM, const char *const sS, int const iA); Student::Student(const char *const sV, const char *const sN, const char *const sM, const char *const sS); Student::Student(const char *const sV, const char *const sN, const char *const sM); Student::Student(const char *const sV, const char *const sN); Student::Student(const char *const sV); Student::Student(); ~Student(); void einlesen(); void ausgeben(); //Set Variablen ??? }; //Definition der Memberfunktionen // Konstruktor mit allen Varianten von Übergebenen Parametern Student::Student(const char *const sV, const char *const sN, const char *const sM, const char *const sS, int const iA) { // Speicher für den Vornamen reservieren sVorname = new string(sV); // Speicher für den Nachname reservieren sNachname = new string(sN); //Speicher für die Matrikelnummer reservieren sMatrikel = new string(sM); //Speicher für das Alter reservieren sStudiengang = new string(sS); //Speicher für Alter reservieren iAlter = new int(iA); } Student::Student(const char *const sV, const char *const sN, const char *const sM, const char *const sS) { // Speicher für den Vornamen reservieren sVorname = new string(sV); // Speicher für den Nachname reservieren sNachname = new string(sN); //Speicher für die Matrikelnummer reservieren sMatrikel = new string(sM); //Speicher für das Alter reservieren sStudiengang = new string(sS); } Student::Student(const char *const sV, const char *const sN, const char *const sM) { // Speicher für den Vornamen reservieren sVorname = new string(sV); // Speicher für den Nachname reservieren sNachname = new string(sN); //Speicher für die Matrikelnummer reservieren sMatrikel = new string(sM); } Student::Student(const char *const sV, const char *const sN) { // Speicher für den Vornamen reservieren sVorname = new string(sV); // Speicher für den Nachname reservieren sNachname = new string(sN); } Student::Student(const char *const sV) { // Speicher für den Vornamen reservieren sVorname = new string(sV); } Student::Student() { } //Destruktor Student::~Student() { delete sVorname; delete sNachname; delete sMatrikel; delete sStudiengang; delete iAlter; } //Einslesen von Studenten Infos void Student::einlesen() { cout << "Bitte Vorname eingeben " ; cin >> *sVorname; cout << endl << "Bitte Nachname eingeben "; cin >> *sNachname; cout << endl << "Bitte Matrikelnummer eingeben: "; cin >> *sMatrikel; cout << endl << "Bitte Studiengang eingeben: "; cin >> *sStudiengang; cout << endl << "Bitte Alter eingeben: "; cin >> *iAlter; } //Ausgabe von Studenten Infos void Student::ausgeben() { cout << "Vorname: " << *sVorname << endl; cout << "Nachname: " << *sNachname << endl; cout << "Matrikelnummer: " << *sMatrikel << endl; cout << "Studiengang: " << *sStudiengang << endl; cout << endl; cout << "Alter: " << *iAlter << endl; cout << endl; } int main() { Student *student = new Student; int iAnzahl; // Anzahl der zu erstellenden Studenten einlesen cout << "Wieviele Studenten wollen Sie anlegen? : "; cin >> iAnzahl; cout << "Sie wollen " << iAnzahl <<" Studenten anlegen!" << endl; for (int i=1; i<=iAnzahl; i++) { cout << endl << "Bitte " << i << ". Student anlegen:" << endl; student[i].einlesen(); } /*Student Student4("0", "0", "0", "0", 0); Student4.einlesen(); Student Student1("Max", "Mustermann", "01234", "IT", 45); Student Student2("Karl", "Mustermann", "01223", "ET", 23); Student Student3("Fritz", "Mustermann", "44562", "DM", 24); Student1.ausgeben(); Student2.ausgeben(); Student3.ausgeben(); Student4.ausgeben();*/ delete student; _getch(); return 0; }
-
[quote="Tyle"]
Ich möchte gerne eine dynamische Anzahl von Instanzen einer Klasse anlegen[/quote[
=> std::vectorich bekomme nun einen Speicherfehler, da ich vermute, dass der Standardkonstuktor aufgerufen wird, der aber noch keinen Speicher für die Variablen der Klasse reserviert hat.
Nö, in der main holst du dir ein Element, benutzt aber anzahl Elemente, was nicht klappen kann.
Benutze hierfür std::vector, da passiert so etwas nicht.
Und warum forderst du den Speicher für die Strings manuell an?
Das macht man nur in Java.
-
... #include <vector> ... int main() { int iAnzahl; // Anzahl der zu erstellenden Studenten einlesen cout << "Wieviele Studenten wollen Sie anlegen? : "; cin >> iAnzahl; cout << "Sie wollen " << iAnzahl <<" Studenten anlegen!" << endl; vector<student> studenten; for (int i=1; i<=iAnzahl; i++) { cout << endl << "Bitte " << i << ". Student anlegen:" << endl; student tmp; tmp.einlesen(); studenten.push_back(tmp); } for(int i = 0; i < studenten.size(); ++i) studenten[i].ausgeben();
-
Tyle schrieb:
Ich möchte gerne eine dynamische Anzahl von Instanzen einer Klasse anlegen ich bekomme nun einen Speicherfehler, da ich vermute, dass der Standardkonstuktor aufgerufen wird, der aber noch keinen Speicher für die Variablen der Klasse reserviert hat.
Hat jemand eine Idee wie ich das Problem lösen kann?
Hier mal der Code:
#include <iostream> #include <iomanip> #include <conio.h> #include <string> using namespace std; // Klassendefinition class Student { private: //Variablen deklarieren string *sMatrikel; string *sVorname; string *sNachname; string *sStudiengang; int *iAlter; public: //Funktionen deklarieren Student( const char *const sV, const char *const sN, const char *const sM, const char *const sS, int const iA); Student::Student(const char *const sV, const char *const sN, const char *const sM, const char *const sS); Student::Student(const char *const sV, const char *const sN, const char *const sM); Student::Student(const char *const sV, const char *const sN); Student::Student(const char *const sV); Student::Student(); ~Student(); void einlesen(); void ausgeben(); //Set Variablen ??? };Stopp stopp stopp ... Das kann man ja nicht mit ansehen ...
Wie wärs mit
#include <string> #include <vector> #include <utility> struct Student { std::string matrikel; std::string vorname; std::string nachname; std::string studiengang; int geburtsjahr; Student(std::string m, std::string v, std::string n, std::string s, int gj) : matrikel (std::move(m)) , vorname (std::move(v)) , nachname (std::move(n)) , studiengang(std::move(s)) , geburtsjahr(gj) {} }; int main() { std::vector<Student> studenten; studenten.emplace_back("12345","Hans","Wurst","Fleicherlogie",1990); studenten.emplace_back("54321","Klaus","Kinski","Ausrasteratik",1950); }Nein, du brauchst normalerweise nicht so viele Zeiger als Datenelemente in einer Klasse. Die machen nur Ärger. Und es macht auch wenig Sinn, eine reine "Daten-Klasse" mit privaten Elementen und dafür getter/setter zu bauen.
-
Die Zeiger waren die Anforderung. Bin noch dabei das Klassenkonzept zu lernen.
Ist meine erste Klasse

-
Tyle schrieb:
Die Zeiger waren die Anforderung.
Ich bin mir sehr sicher, dass du das falsch verstanden hast. Zeiger auf std::string machen 0 Sinn.
Hmm, Zeiger auf Zeichenketten...
Bist du sicher, dass du C++ machst, kein C? Wird oft verwechselt.
-
Stimmt, die Zeiger waren nicht unbedingt erfordert.
Und ja es ist C++... sonst würden ja keine Klassen vorkommen.Der Code funktioniert aber auch nicht. Habe das mal ausprobiert, bekomme dort auch ne Fehlermeldung vom Speicher bei der Ausführung:
#include <vector> ... int main() { int iAnzahl; // Anzahl der zu erstellenden Studenten einlesen cout << "Wieviele Studenten wollen Sie anlegen? : "; cin >> iAnzahl; cout << "Sie wollen " << iAnzahl <<" Studenten anlegen!" << endl; vector<Student> studenten; for (int i=1; i<=iAnzahl; i++) { cout << endl << "Bitte " << i << ". Student anlegen:" << endl; Student tmp; tmp.einlesen(); studenten.push_back(tmp); } for(int i = 0; i < studenten.size(); ++i) studenten[i].ausgeben();
-
Wie sehen Student und Student::einlesen aus?
-
Tyle schrieb:
Die Zeiger waren die Anforderung. Bin noch dabei das Klassenkonzept zu lernen.
Ist meine erste Klasse

Du hast viel zuviele Sterne ---> das mit den Zeigern ist Mist. Wenn das die - bescheuerte - Anforderung ist, lern erst das Zeigerkonzept.
-
Das ist megamässig schlechter C++ Stil den euer Professor euch da beibringt.
-
Der Lehrstuhl von OOP ist wirklich nicht sonderlich gut. Das mussten wir leider auch schon feststellen.
So ich habe mich nochmal drangesetzt und das Programm jetzt vernünftig geschrieben und auch wesentlich unkomplizierter.
Das mit den Zeigern habe ich falsch verstanden und ist daher auf meinen Mist gewachsen.
Hier das Programm:
#include <iostream> #include <string> using namespace std; class Student { public: void einlesen(); void ausgeben(); Student(); ~Student(); private: string vorname_; string nachname_; string matrikel_; string studiengang_; int alter_; }; void Student::einlesen() { cout << "Bitte Vornamen eingeben: "; cin >> vorname_; cout <<endl << "Bitte Nachname eingeben: "; cin >> nachname_; cout << endl << "Bitte Matrikelnummer eingeben: "; cin >> matrikel_; cout << endl << "Bitte Studiengang eingeben: "; cin >> studiengang_; cout << endl << "Bitte ihr Alter eingeben: "; cin >> alter_; cout << endl; } void Student::ausgeben() { cout << matrikel_ <<", " << vorname_ << " " << nachname_ << endl; cout << "Alter: " << alter_ << " Jahre" << endl; cout << "Studiengang: " << studiengang_ << endl; } //Konstrukor und Destruktor Student::Student() {} Student::~Student() {} int main () { int n; cout << "Bitte die Anzahl der Studenten angeben die Sie anlegen möchten: "; cin >> n; cout << endl; Student *studenten = new Student[n]; for (int i=0; i<n; i++) { cout << "Bitte " << (i+1) << ". Studenten anlegen!" << endl; studenten[i].einlesen(); } for (int i=0; i<n; i++) { studenten[i].ausgeben(); cout << endl; } delete [] studenten; system("pause"); return 0; }
-
Wenn dein Konstruktor und Destruktor leer sind, bietet es sich an, diese wegzulassen.
http://en.wikipedia.org/wiki/Special_member_functionsWas hier am Design noch ungünstig ist, ist die Vermischung von Schnittstelle und Programmlogik. Ein Student hat keine Konsolenausgabe* oder -eingabe, das kannst du leicht an dir selber mal ausprobieren
. Er kann seine Daten irgendwo hinterlassen und als Zugeständnis an die Existenz des Studenten im Computer können diese Daten sicherlich auch wieder gelesen werden. Aber dass dies unbedingt über cin/cout erfolgen soll, das sollte einem Studenten an sich eigentlich einmal egal sein, das gehört nicht zum Studentsein.Konkret will ich auf Folgendes hinaus, was aber bei Euch wahrscheinlich noch nie drangekommen ist (und vielleicht auch nie wird):
Google: c++ overload stream operator*: cout und cin stehen natürlich für character out und -in, nicht console. Muss auch praktisch nicht identisch sein, wusste bloß nicht wie ich das auf Deutsch ausdrücken sollte.
-
Hinweis: Statt der Funktionen eingeben() und ausgeben() sollte man normalerweise einen eigenen Eingabeoperator (operator >>) bzw. Ausgabeoperator (operator <<) benutzen oder die Daten direkt im Konstruktor belegen. Da diese Aufgabe aber nur als vereinfachter Einstieg dienen soll, werden hier noch keine Operatoren und Konstruktoren verwendet.
Meinst du das?

Kommt wohl noch später, bin jetzt gerade an der nächsten Klasse dran, die schon was umfangreicher wird und auch das header Prinzip umfasst.
Edit:
Später ist wohl jetzt, ab jetzt muss ich die Überladung der Stream-Operatoren lernen.
-
Tyle schrieb:
Meinst du das?

Ja. gut zu wissen, dass es dem Lehrer nicht unbekannt ist.
-
Gibt es dazu ein gutes Tutorial, welches das Konzept anschaulich erklärt? Ich brauche das nämlich ab sofort.
Glaube hier wird das gut beschrieben:
http://www.c-plusplus.net/forum/232010-full