2016-10-09 2 views
-2

Die Funktionsweise des Codes besteht darin, dass es eine reine virtuelle Basisklasse namens "Module" mit Unterklassen von "Living", "Manufacturing" und "PowerGen" gibt, die einige der virtuellen Funktionen verwendet. In der Haupttreiberdatei kann ich erfolgreich eine Liste von Modulen aus einer Datei lesen und sie in einem Vektor von Modulzeigern speichern. Das Problem tritt auf, wenn ich die virtuelle Anzeigefunktion verwenden möchte, um die Moduldetails dieses Vektorelements anzuzeigen. Ich stehe vor einem Segmentierungsfehler. Jede Hilfe würde sehr geschätzt werden!Aufruf der virtuellen Funktion - Segmentierungsfehler

Class Module 
{ 
public: 
    Module() = default; 
    explicit Module(const string& purpose, const string& id) 
    { 
     this->purpose = purpose; 
     this->id = id; 
    } 
    explicit Module(const string& purpose) { this->purpose = purpose; } 
    virtual ~Module() { } 

    virtual void setCrew() = 0; 
    virtual void display() const = 0; 
    void addCrew(const string& name) 
    { 
     crew_list.push_back(Crew(name)); 
     ++number_of_crew; 
    } 
    void setPowerReq(double power) { this->power = power; } 
    void setMaxCrew(int max_crew) { this->max_crew = max_crew; } 

    string getPurpose() { return purpose; } 
    string getId() { return id; } 
    int getNumberOfCrew() { return number_of_crew; } 
    int getMaxCrew() { return max_crew; } 
    double getPower() { return power; } 

    friend ostream& operator << (ostream& os, const Module& m); 
    friend ofstream& operator << (ofstream& os, const Module& m); 
    friend ifstream& operator >> (ifstream& is, Module& m); 

private: 
    string purpose = "unknown"; 
    string id = "unknown"; 
    int number_of_crew = 0; 
    int max_crew = 0; 
    double power = 0; 
    vector<Crew> crew_list; 
}; 


class Living : public Module 
{ 
public : 

    Living() = default; 
    explicit Living(const string& purpose); 
    Living(int meals, const string& id); 
    void setCrew() 
    { 
     setMaxCrew(floor(meals/3)); 
     setPowerReq(meals * 1.4); 
    } 
    void display() const 
    { 
     cout << *this; 
    } 

    friend ofstream& operator << (ofstream& os, const Living& l); 
    friend ifstream& operator >> (ifstream& is, Living& l); 

private : 
    int meals = 0; 
    static string type; 
}; 

class Manufacturing : public Module 
{ 
public: 
    Manufacturing() = default; 
    Manufacturing(const string& product, int quantity, const string& id); 
    explicit Manufacturing(const string& purpose); 
    void setCrew() 
    { 
     setPowerReq(quantity * 6); 
     setMaxCrew(maxCrew); 
    } 
    void display() const 
    { 
     cout << *this; 
    } 

    friend ofstream& operator << (ofstream& os, const Manufacturing& m); 
    friend ifstream& operator >> (ifstream& is, Manufacturing& m); 

private: 
    static string type; 
    string product = "unknown"; 
    static int maxCrew; 
    int quantity = 0; 
}; 

class PowerGen : public Module 
{ 
public: 
    PowerGen() = default; 
    PowerGen(int number_of_generators, const string& id); 
    explicit PowerGen(const string& purpose); 
    void setCrew() 
    { 
     setMaxCrew(0); 
     setPowerReq(-(number_of_generators * 7)); 
    } 
    void display() const 
    { 
     cout << *this; 
    } 

    friend ofstream& operator << (ofstream& os, const PowerGen& p); 
    friend ifstream& operator >> (ifstream& is, PowerGen& p); 

private: 
    static string type; 
    const int max_generators = 8; 
    int number_of_generators = 0; 
}; 

Portion relevant von der Haupttreiberdatei, die beim Aufruf bewirkt, dass die segmenation Fehler:

if(cityVector.size() > 0) 
    { 
     cout << "\nHere is the complete City" << endl; 
     for (auto iter : cityVector) 
     { 
     iter->display(); 
     cout << endl << endl; 
     } 
    } else { 
     cout << "\nThere are no Modules in the City" << endl; 
    } 

Dies ist, wie ich die Daten aus einer Datei geladen, wo VMOD = Vektor:

void load(VMOD & cityVector) 
{ 
    string filename; 
    cout << "Please enter a filename >> "; 
    getline(cin, filename); 
    ifstream fin; 
    fin.open(filename); 
    if (!fin.fail()) 
    { 
     while (!fin.eof()) 
     { 
     string purpose; 
     getline(fin, purpose); 
     if (purpose == "Living") 
     { 
      Living object(purpose); 
      loadObject(cityVector, object, fin); 
      } else if (purpose == "Manufacturing") 
     { 
      Manufacturing object(purpose); 
      loadObject(cityVector, object, fin); 
     } else if (purpose == "Power Generation") 
     { 
      PowerGen object(purpose); 
      loadObject(cityVector, object, fin); 
     } else { 

     } 
     } 
     cout << "The city has " << cityVector.size() << " modules!" << endl; 
    } else { 
     cout << "File does not exist... " << endl; 
    } 
    fin.close(); 
} 

template<typename T> 
void loadObject(VMOD & cityVector, T object, ifstream& fin) 
{ 
    fin >> object; 
    Module* mptr; 
    mptr = &object; 
    cityVector.push_back(mptr); 
} 

Mit der Datei wie folgt aussehen:

Living 
L1 
5 
21 
2 
First Person 
Fourth Person 
15 
Manufacturing 
M1 
10 
12 
4 
Second Person 
Third Person 
Fifth Person 
Sixth Person 
C++ ness 
2 
Power Generation 
P1 
0 
-14 
0 
2 
+0

Das richtige Werkzeug, um solche Probleme zu lösen ist Ihr Debugger. Sie sollten Schritt für Schritt durch Ihren Code * gehen, bevor Sie auf Stack Overflow nachfragen. Für weitere Hilfe lesen Sie bitte [Wie kleine Programme zu debuggen (von Eric Lippert)] (https://ericlippert.com/2014/03/05/how-to-debug-small-programs/). Zumindest sollten Sie Ihre Frage bearbeiten, um ein [minimales, vollständiges und verifizierbares] (http://stackoverflow.com/help/mcve) Beispiel einzufügen, das Ihr Problem zusammen mit den Beobachtungen, die Sie in der Debugger. –

+0

Der Übeltäter ist wahrscheinlich der Code, den Sie verwenden, um die Objekte in der Datei zu speichern und sie aus der Datei zu lesen. Bitte poste ein [mcve]. –

+0

Sie haben alle diese Klassen, aber Sie konnten uns nichts zeigen, was diese Klassen instanziiert und ausübt. – PaulMcKenzie

Antwort

0

Sie haben ein Problem mit einem ungeeigneten Zeiger.

template<typename T> 
void loadObject(VMOD & cityVector, T object, ifstream& fin) 
{ 
    // object is a function local object 
    // since it is passed by value. 
    fin >> object; 
    Module* mptr; 

    // This is a pointer to a local object. 
    // It is invalid when the function returns. 
    mptr = &object; 

    // Storing a pointer that will be a dangling pointer as soon 
    // the function returns. 
    cityVector.push_back(mptr); 
} 

Sie müssen dynamisch zugewiesenen Speicher für die wiederhergestellten Objekte verwenden und sie in cityVector speichern.

Sie müssen sicherstellen, dass der Speicher freigegeben wird, wenn Sie ihn nicht mehr verwenden.

template<typename T> 
void loadObject(VMOD& cityVector, ifstream& fin) 
{ 
    T* objectPtr = new T; 
    fin >> *objectPtr; 
    cityVector.push_back(objectPtr); 
} 

und nennen es die folgende Syntax verwenden:

loadObject<LivingObject>(cityVector, fin); 
+0

Danke, arbeitete wie ein Charme! –

Verwandte Themen