この異種リストに問題があります。私はテキストファイルに渡され、それを使ってオブジェクトのメンバーデータを読み込んでリストに追加します。これはこれを初めて使ったときのことで、なぜそれが正しく動作しないのか理解できません。ポインタが配列されているそれぞれのオブジェクトのアドレスをポインタに保存する必要がありますか?しかし、私がテストすると、(* 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