이 이기종 목록을 채우는 데 문제가 있습니다. 텍스트 파일을 전달한 다음이를 사용하여 개체의 멤버 데이터를 채운 다음 목록에 추가합니다. 이것은 이것을 처음 사용하는 것이고 왜 제대로 작동하지 않는지 이해할 수 없습니다. 각 채워진 객체 주소를 포인터 배열의 포인터에 저장해야합니다. 맞습니까? 그러나 테스트 할 때 (* list) [0]의 단일 위치에만 저장된다는 것을 알 수 있습니다. 가장 관련성이 높은 부분은 main.cpp에서 올 것입니다. 고맙습니다!이기종 목록 및 동적 배열 할당
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' - 만료 예정인 자동 변수의 주소를 저장하여 그 주소를 쓸모 없게 만들었습니다. 마찬가지로이 코드에서 다른 모든 유사한 저장합니다. 'std :: vector>'또는 이와 유사한 관리 형 포인터 솔루션을 사용하는 것이 좋습니다. –
WhozCraig
동적 메모리 할당을 배우는 것이 아니라면하지 마십시오. 대신 [표준 컨테이너] (http://en.cppreference.com/w/cpp/container)를 사용하십시오 (나는''std :: vector' ''를 권장합니다 (http://en.cppreference.com/w/cpp/)). 컨테이너/벡터)를 시작합니다. 또한 컨테이너에있는 객체에 대한 포인터를 저장하지 말고 실제 객체 인스턴스를 저장하십시오. 마지막으로, 당신이 만드는 것은 단어의 컴퓨터 과학 의미에서 "목록"이 아니라 오히려 객체에 대한 동적 인 크기의 배열 (포인터)입니다. –
"컨테이너의 오브젝트 인스턴스"는 다형성 인 경우 오브젝트 분할로 연결됩니다. 여기서는 그렇지 않지만주의해야 할 점은 std :: vector는 내부 버퍼를 재 할당 할 수 있으므로 객체가 이동할 수 있습니다. 이들에 대한 포인터 또는 참조가 필요하면 유효하지 않게됩니다. 따라서 우리는 재 할당되지 않은 컨테이너 (예 : std :: list) 또는 포인터 (-> WhozCraig의 주석)로 되돌아 가야합니다. – Aconcagua