So habe ich ein Problem, diese heterogene Liste zu füllen. Ich bin in einer Textdatei übergeben worden und benutze es, um die Mitgliedsdaten der Objekte zu füllen und sie dann der Liste hinzuzufügen. Dies ist das erste Mal, dass ich das benutze und ich kann nicht verstehen, warum es nicht richtig funktioniert. Es sollte jede Adresse der aufgefüllten Objekte in einem Zeiger im Zeiger-Array speichern, richtig? Aber wenn ich es teste, kann ich sehen, dass es nur an der einzelnen Stelle von (* list) [0] speichert. Der relevanteste Teil wird wahrscheinlich von main.cpp kommen. Vielen Dank!Heterogene Liste und dynamische Array-Zuweisung
main.cpp
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include "student.h"
using namespace std;
int main()
{
string inputFileName;
string outputFileName;
cout << "Please enter the input file name: ";
getline(cin, inputFileName);
ifstream inputFile;
int NUMBEROFENTRIES;
inputFile.open(inputFileName.c_str()); //CLOSE
if(inputFile){
NUMBEROFENTRIES = int(inputFile.get())-int('0');
}else{
cout << "Failed to open file." << endl;
}
Student ** list; //create a pointer to Student pointer
list = new Student*[NUMBEROFENTRIES]; //dynamically allocated list of Student pointers
for(int i = 0; i < NUMBEROFENTRIES; i++)
{
string uselessNewLine;
getline(inputFile, uselessNewLine);
string tempfirstname;
string templastname;
getline(inputFile, templastname, ',');
inputFile.get();
getline(inputFile, tempfirstname);
char tempcourse = inputFile.get();
if(tempcourse == 'b'||tempcourse == 'B')
{
BioStudent bobj;
bobj.setNameAndCourse(tempfirstname, templastname, tempcourse);
string garbage;
getline(inputFile, garbage, ' ');
bobj.SetGrades(inputFile);
list[i] = &bobj; //I assume this is where the error is but i should be incrementing?
}
else if(tempcourse == 't' || tempcourse == 'T')
{
TheaterStudent tobj;
tobj.setNameAndCourse(tempfirstname, templastname, tempcourse);
string garbage;
getline(inputFile, garbage, ' ');
tobj.SetGrades(inputFile);
list[i] = &tobj; //I assume this is where the error is but i should be incrementing?
}
else if(tempcourse == 'c' || tempcourse == 'C')
{
CompsciStudent cobj;
cobj.setNameAndCourse(tempfirstname, templastname, tempcourse);
string garbage;
getline(inputFile, garbage, ' ');
getline(inputFile, garbage, ' ');
cobj.SetGrades(inputFile);
list[i] = &cobj; //I assume this is where the error is but i should be incrementing?
}else{
cout << "ERROR" << endl;
}
cout << (*list[0]).course << endl;
}
delete [] list;
return 0;
}
student.h
#include <string>
#include <iostream>
using namespace std;
class Student
{
public:
virtual double GetAverage()=0; //Another pure virtual function
void setNameAndCourse(string fn, string ln, char tc);
Student();
char course;
char GetCourse();
protected:
string firstName;
string lastName;
private:
};
class BioStudent: public Student
{
public:
BioStudent();
void SetGrades(ifstream &input);
double GetAverage();
private:
int labGrade;
int test1;
int test2;
int test3;
int finalExam;
};
class TheaterStudent: public Student
{
public:
TheaterStudent();
void SetGrades(ifstream &input);
double GetAverage();
private:
int participation;
int midterm;
int finalExam;
};
class CompsciStudent: public Student
{
public:
CompsciStudent();
void SetGrades(ifstream &input);
double GetAverage();
private:
int assign1;
int assign2;
int assign3;
int assign4;
int assign5;
int assign6;
double assignAverage;
int test1;
int test2;
int finalExam;
};
student.cpp
#include "student.h"
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
using namespace std;
Student::Student()
{
firstName = "";
lastName = "";
course = ' ';
}
void Student::setNameAndCourse(string fn, string ln, char tc)
{
firstName = fn;
lastName = ln;
course = tc;
}
char Student::GetCourse()
{
return course;
}
BioStudent::BioStudent()
{
labGrade = 0;
test1 = 0;
test2 = 0;
test3 = 0;
finalExam = 0;
}
void BioStudent::SetGrades(ifstream& input)
{
input >> labGrade;
input >> test1;
input >> test2;
input >> test3;
input >> finalExam;
}
double BioStudent::GetAverage()
{
double toReturn = 0.0;
toReturn = ((labGrade*.3) + (test1*.15) + (test2*.15) + (test3*.15) + (finalExam*.25));
return toReturn;
}
TheaterStudent::TheaterStudent()
{
participation = 0;
midterm = 0;
finalExam = 0;
}
void TheaterStudent::SetGrades(ifstream &input)
{
input >> participation;
input >> midterm;
input >> finalExam;
}
double TheaterStudent::GetAverage()
{
double toReturn = 0.0;
toReturn = ((participation*.4)+(midterm*.25)+(finalExam*.35));
return toReturn;
}
CompsciStudent::CompsciStudent()
{
assign1 = 0;
assign2 = 0;
assign3 = 0;
assign4 = 0;
assign5 = 0;
assign6 = 0;
assignAverage = 0.0;
test1 = 0;
test2 = 0;
finalExam = 0;
}
void CompsciStudent::SetGrades(ifstream &input)
{
input >> assign1;
input >> assign2;
input >> assign3;
input >> assign4;
input >> assign5;
input >> assign6;
input >> test1;
input >> test2;
input >> finalExam;
}
double CompsciStudent::GetAverage()
{
double toReturn = 0.0;
assignAverage = ((assign1+assign2+assign3+assign4+assign5+assign6)/6);
toReturn = ((assignAverage*.3)+(test1*.2)+(test2*.2)+(finalExam*.3));
return toReturn;
}
'list [i] = & bobj' - Sie haben gerade die Adresse einer automatischen Variablen gespeichert, die bald abläuft, wodurch diese Adresse nutzlos wird. Ebenso in allen anderen ähnlichen Speichern in diesem Code. Ich schlage vor, Sie verwenden eine 'std :: vector>' oder ähnliche verwaltete Zeigerlösung. –
WhozCraig
Wenn die Übung nicht die dynamische Speicherzuordnung lernen soll, tun Sie es nicht. Verwenden Sie stattdessen einen [Standardcontainer] (http://en.cppreference.com/w/cpp/container) (ich empfehle ['std :: vector'] (http://en.cppreference.com/w/cpp/) Container/Vektor) zu beginnen). Speichern Sie auch keine Zeiger auf Objekte im Container, sondern auf tatsächliche Objektinstanzen. Schließlich ist das, was Sie erstellen, keine "Liste" in der computerwissenschaftlichen Bedeutung des Wortes, sondern ein dynamisch großes * Array * (Zeiger auf) Objekte. –
"Objektinstanzen im Container" führen zum Objekt-Slicing, wenn diese polymorph sind - was hier der Fall ist. Nicht der Fall hier, aber erwähnenswert: std :: vector kann seinen internen Puffer neu zuweisen, so dass Objekte sich bewegen können. Wenn Zeiger oder Verweise auf diese notwendig sind, werden sie dann ungültig. Also brauchen wir entweder einen nicht neu zuweisbaren Container (z. B. std :: list) oder wir sind zurück auf Zeiger (-> WhozCraigs Kommentar dann). – Aconcagua