-2

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; 
} 
+2

'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

+1

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. –

+1

"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

Antwort

0

Sie sind righ t, ist das Problem hier:

list[i] = &bobj; //I assume this is where the error is but i should be incrementing? 

und der Grund ist, weil bobj auf Stapel ist wie folgt definiert:

BioStudent bobj; 

so wird es zerstört werden, sobald seine umgebenden Gültigkeitsbereich endet, und dann Ihre Liste wird halte einen baumelnden Zeiger.

Was Sie wollen, ist dynamisch zugewiesen Objekt:

BioStudent* bobj = new BioStudent; 

und dann:

list[i] = bobj; 

auch vergessen Sie nicht, Ihre Objekte freizugeben, oder besser zu nutzen intelligente Zeiger.

+0

Ah du bist fantastisch! Ich denke, ich bin immer noch verwirrt über die dynamische Zuweisung, ich werde mir später noch ein paar Videos ansehen. Wann wäre die beste Zeit, um sie zu entziehen? Das ist der 'delete bobj' Teil richtig? – SWilt

+0

@SWilt heben sie auf, bevor sie 'delete [] list; Eine andere Sache ist, dass Sie einen virtuellen Destruktor in Ihrer Student-Klasse benötigen, sonst haben Sie ein Undefined Behavior - lesen Sie hier http://StackOverflow.com/questions/8599225/virtual-destructor-and-undefined-behavior für mehr dazu. – marcinj