2016-10-09 2 views
-2

Принцип работы кода заключается в том, что существует базовый чистый виртуальный класс под названием «Модуль» с подклассами «Living», «Manufacturing» и «PowerGen», который использует некоторые из виртуальных функций. В основном файле драйвера я успешно могу прочитать список модулей из файла и сохранить их в векторе указателей модулей. Проблема возникает, когда я хочу использовать функцию виртуального отображения, чтобы отобразить детали этого элемента элемента вектора. Я столкнулся с ошибкой сегментации. Любая помощь приветствуется!Вызов виртуальной функции - ошибка сегментации

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

Порция отношение от основного файла драйвера, который при вызове вызывает ошибку segmenation:

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

Это, как я загрузил данные из файла, где VMOD = вектор:

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); 
} 

С файлом выглядят так:

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

Правильный инструмент для решения таких проблем является ваш отладчик. Перед тем, как просить о переполнении стека, вы должны пропустить свой код по очереди *. Для получения дополнительной информации, пожалуйста, прочтите [Как отлаживать небольшие программы (Эрик Липперт)] (https://ericlippert.com/2014/03/05/how-to-debug-small-programs/). Как минимум, вы должны \ [изменить] ваш вопрос, чтобы включить пример [Минимальный, полный и проверенный] (http://stackoverflow.com/help/mcve), который воспроизводит вашу проблему, а также замечания, сделанные вами в отладчик. –

+0

Виновником, скорее всего, является код, который вы используете для сохранения объектов в файле и чтения их из файла. Пожалуйста, опубликуйте [mcve]. –

+0

У вас есть все эти классы, но вы не смогли показать нам что-либо, что создает и использует любой из этих классов. – PaulMcKenzie

ответ

0

У вас проблема с висячим указателем.

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); 
} 

Вы должны использовать динамически выделенную память для восстановленных объектов и сохранять их в cityVector.

Вам нужно будет убедиться, что память освобождена после того, как вы закончите использовать ее.

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

и вызвать его, используя следующий синтаксис:

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

Спасибо, работал как шарм! –

Смежные вопросы