2016-12-03 3 views
0

Ich bin ein Anfänger C++ - Programmierer, der derzeit ein Student an meiner lokalen Universität ist. Ich mache diese Aufgabe und mir wird gesagt, ich solle eine verkettete Liste einer Klasse namens Auto erstellen, um einen "Zug" zu erstellen. Ich habe zwei abgeleitete Klassen, die einfach anders drucken.C++ doppelt frei oder Korruption Fehler am Ende des Bereichs

Was ich tun möchte, ist eine Liste von Waggons zu erstellen, und zwei Zeiger zeigen auf das aktuelle Auto von jedem Typ (Stuhl und Schlafen), so weiß ich, wann der Benutzer einen Sitz eines bestimmten Typs innerhalb buchen möchte der Zug, ich weiß genau wo ich hingehen soll. Wenn ein Zug voll ist, ist geplant, einen neuen Zug dieses Typs auf das Ende zu setzen. Bsp .: Der letzte Platz des Schlafwagens ist reserviert, ein neues Schlafwagenfahrzeug wird erstellt und am Ende des Zuges platziert. Der aktuelle Schlafwagenzeiger zeigt nun auf das neue Auto am Ende der Liste.

Unten ist der Code, den ich für dieses Programm haben:

carTest.cc

int main() 
{ 
    int trainId = 0; 
    list<Car> train; 

    // Testing Car Default Constructor 

    // Testing Car Constructor 
    //cout << "Creating a \"Chair car\"... " << endl; 

    Car* currChair = nullptr, *currSleep = nullptr; 
    train.push_back(ChairCar(trainId++)); 
    currChair = &train.back(); 
    train.push_back(SleepingCar(trainId++)); 
    currSleep = &train.back(); 

    // Testing bookSeat 
    //book_seat_test(car2); 

    // Testing isTypeAvailable 
    //is_type_available_test(car2); 

    // Testing isBooked 
    //is_booked_test(car2); 

    // Testing mostAvailable 
    //most_available_test(car2); 

    // Testing firstAvailable 
    //first_available_test(car2); 

    // Testing getSeatNumber 
    ///get_seat_number_test(car2); 

    // Testing getIndex 
    //get_index_test(car2); 

    // Testing bookFirstAvailable 
    //book_first_available_test(car2); 

    // Testing chairCar printStatus 
    //chairCar_print_status_test(*currChair); 

    // Testing sleepingCar printStatus 
    //sleepingCar_print_status_test(*currSleep); 

    currSleep = nullptr; 
    currChair = nullptr; 
    return 0; 
} 

car.h

class Car 
{ 
public: 
    class Seat 
    { 
    public: 
    Seat() : row(-1), col(-1) {}; 
    Seat(int i, int j) : row(i), col(j) {}; 
    int getRow() const { return row; } 
    int getCol() const { return col; } 

    private: 
    int row; 
    int col; 
    }; 

public: 
    // Contructors 
    Car(); 
    explicit Car(int, int, int); 

    // Deconstructor 
    ~Car(); 

    // Public Member Functions 
    bool bookSeat(int, int); 
    bool isTypeAvailable(int) const; 
    bool isBooked() const; 
    int mostAvailable() const; 
    int firstAvailable(int) const; 
    int getSeatNumber(int, int) const; 
    Seat getIndex(int) const; 
    int bookFirstAvailable(int); 
    virtual void printStatus(int) const; 

protected: 
    int carNumber; 
    int rows; 
    int cols; 
    bool** plan; 
    int* numAvailable; 
    int columnSeperation; 

    void init(); 
}; 

car.cc

// function: Deconstructor 
// Description: 
//    The Deconstructor simply frees the dynamically allocated memory 
// of the data members plan and numAvailable if the members are not pointing 
// to the nullptr. 
Car::~Car() 
{ 
    if(plan != nullptr) 
    { 
     delete[] plan; 
     plan = nullptr; 
    } 

    if(numAvailable != nullptr) 
    { 
     delete[] numAvailable; 
     numAvailable = nullptr; 
    } 
} 

chairCar.h

class ChairCar : public Car 
{ 
public: 
    ChairCar(); 
    ChairCar(int); 
protected: 
    void printStatus(int seatNumber) const; 
}; 

#endif 

chairCar.cc

#include "chairCar.h" 

ChairCar::ChairCar() 
    : Car() 
{ 

} 

ChairCar::ChairCar(int id) 
    : Car(7,4,id) 
{ 

} 

void ChairCar::printStatus(int seatNumber) const 
{ 
    int maxSeatNumber = (rows-1)*cols+(cols-1); 
    if(seatNumber > maxSeatNumber || seatNumber < 0) 
    throw OutOfRangeException(seatNumber, 0, maxSeatNumber); 

    cout << setw(columnSeperation) << ' ' << " |"; 
    cout << setw(columnSeperation) << "WL"; 
    cout << setw(columnSeperation) << "ML"; 
    cout << setw(columnSeperation) << "MR"; 
    cout << setw(columnSeperation) << "WR"; 
    cout << endl; 
    Car::printStatus(seatNumber); 
} 

Schlafwagen ist genau das gleiche wie Chair Car außer unterschiedliche Argumente an die Basiskonstruktor gesendet werden. Wenn ich den Code in der Hauptfunktion laufen bekomme ich

Fehler in `/ home/w1llbedone/Programmierung/cpsc2620/assn/a4/carTest ': Doppel frei oder Korruption (fasttop): 0x0000000000608010

Ich habe versucht, die currCar Zeiger auf nullptr vor Ende des Bereichs zu setzen, um diesen Fehler zu vermeiden. Kann mir jemand erklären, warum das passiert? Dies ist meine erste Veröffentlichung auf StackExchange, daher entschuldige ich mich für den Mangel an Informationen. Jede Hilfe würde sehr geschätzt werden.

+0

Sie sollten nicht ein SleepCar in, 'list train;'. Meine Vermutung ist, dass es über copy ctor in ein Auto geschnitten wurde. Der Umfang von SleepCar ist in der Push_back, so dass seine Ressource freigegeben wird. Und am Ende von main, dtor der Kopie (Car) in der Liste ist auch befreit, also das doppelte frei. Verwenden Sie 'list Train' oder noch besser 'list >'. Auch ~ Car() sollte virtuell sein. –

+0

'Car' hat einen nicht-trivialen Destruktor, aber ich sehe keinen Kopierkonstruktor oder Kopierzuweisungsoperator, also löschst du deine dynamisch zugewiesenen Mitglieder doppelt. –

+4

Mögliches Duplikat von [Was ist die Dreiregel?] (Http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three) –

Antwort

1

Es gibt mindestens zwei Hauptfehler im teilweise gezeigten Code. Fehler # 1:

list<Car> train; 

// ... 

train.push_back(ChairCar(trainId++)); 

Dies ist ein Lehrbuch von object slicing. train ist ein std::list von Car s. Der gezeigte Code erstellt einen ChairCar und fügt ihn in die Liste ein. Dadurch wird die Unterklasse ChairCar abgeschnitten und die Superklasse Car in die Liste kopiert.

Fehler # 2 ist der primäre Fehler hier: diese Klasse violates the Rule Of Three. Car 's Destruktor eindeutig delete s Klassenmitglieder, die in dynamischen Umfang erstellt wurden. Die Klasse Car definiert jedoch weder einen Kopierkonstruktor noch den Zuweisungsoperator.Dies schließt die Chancen aus, dass diese Klasse als Three-Three-konform gilt.

Also, diese beiden Fehler führen zu einer tödlichen Kombination. Während des ersten Objekt-Slicing wird das temporäre Objekt ChairCar zerstört, aber erst, nachdem eine Kopie seiner Superklasse Car in den Container der Liste kopiert wurde. Als Teil der Zerstörung ist der Destruktor Cardelete s seine dynamisch beschränkten Klassenmitglieder.

Dann schließlich wird die Liste Container zerstört und die Car, in der Liste abgeschnitten, zerstört wird, und seine destructor Versuche, delete die Zeiger, die bereits delete d waren.

Spiel vorbei.

Verwandte Themen