-2

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

'list [i] =&bobj' - 有効期限が切れている自動変数のアドレスを保存しただけで、そのアドレスは無駄になります。同様に、このコードでは他のすべての同様の保存で。私はあなたが 'std :: vector >'または同様のマネージドポインターソリューションを使用することをお勧めします。 – WhozCraig

+1

ダイナミックメモリ割り当てを学習することが練習でない限り、実行しないでください。代わりに[標準コンテナ](http://en.cppreference.com/w/cpp/container)を使用してください(私は['std :: vector']を推奨します(http://en.cppreference.com/w/cpp/コンテナ/ベクトル)を開始します)。また、コンテナ内のオブジェクトへのポインタを格納するのではなく、実際のオブジェクトインスタンスを格納します。最後に、あなたが作成しているのは、コンピュータサイエンスの意味でのリストではなく、むしろオブジェクトへの(ポインタへの)動的なサイズの配列です。 –

+1

"コンテナ内のオブジェクトインスタンス"は、多形である場合、オブジェクトのスライスにつながります。ここではそうではありませんが、注意する価値があります。std :: vectorは内部バッファを再割り当てできるため、オブジェクトが動く可能性があります。これらへのポインタや参照が必要な場合は、それらは無効になります。したがって、再配置しないコンテナ(たとえばstd :: list)か、ポインタ( - > WhozCraigのコメント)に戻る必要があります。 – Aconcagua

答えて

0

あなたはRIGHです

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

と、次のようにbobjがスタック上に定義されているためである:tは、問題はここにある

BioStudent bobj; 
ので

囲みスコープが終了したら、それは破壊され、その後、あなたのリストにはなりますぶら下がっているポインタを保持する。

BioStudent* bobj = new BioStudent; 

、その後::オブジェクトを動的に割り当てられて何がしたい

list[i] = bobj; 

はまたあなたのオブジェクトの割り当てを解除するのを忘れ、またはより良いスマートポインタを使用してはいけません。

+0

ああ、あなたは素晴らしいです!私はまだダイナミックな割り当てについて混乱していると思う、私は今夜後にいくつかのビデオを見ます。いつ割当てを解除するのが最適な時期でしょうか?それは '削除ボブ'の部分の権利ですか? – SWilt

+0

@SWiltは 'delete [] listの直前でそれらの割り当てを解除します。別のことは、あなたのStudentクラスに仮想デストラクタが必要なことです。そうでなければ、未定義の動作が発生します。詳細はこちらhttp://stackoverflow.com/questions/8599225/virtual-destructor-and-undefined-behaviorを参照してください。 – marcinj

関連する問題