2016-12-03 70 views
0

我是新手C++程序员,他目前是我本地大学的一名学生。我正在做这个任务,并且我被告知创建一个名为Car的类的链表来创建一个“火车”。我有两个派生类,只是打印不同。C++ double免费或在范围结束时出现错误错误

我想要做的是创建列车车厢列表,并且有两个指向每种类型(椅子和睡觉)的当前车的指针,以便我知道用户何时想要预订某种类型的座位火车,我知道到哪里去。当一列火车满了时,计划就是把这种新的列车结束。例如:睡车的最后一个座位被预订,一辆新的睡车将被创建并放在火车的尽头。现在的睡车指针现在将指向列表末尾的新车。

下面是我对这个程序的代码:

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

睡车是完全一样的主席轿车除了不同的参数发送到基构造函数。当我运行在主函数中的代码,我得到

错误 `/家庭/ w1llbedone /编程/ cpsc2620/ASSN/A4/carTest“:双重释放或腐败(fasttop):0x0000000000608010

我试图在范围结束前设置currCar指针nullptr以避免此错误。谁能向我解释为什么会发生这种情况?这是我第一次在StackExchange上发布,所以我对缺少任何信息表示歉意。任何帮助将不胜感激。

+0

您不应该将SleepCar推入“列表列车”。我猜想它已经通过copy ctor切片成Car了。 SleepCar的范围在push_back中,因此其资源被释放。在main的结尾,列表中副本(Car)的dtor也被释放,因此double free。使用列表列车'或更好'列表>'。另外〜Car()应该是虚拟的。 –

+0

'Car'有一个非平凡的析构函数,但是我没有看到任何拷贝构造函数或拷贝赋值操作符,所以你会双重删除你的动态分配的成员。 –

+4

[三条法则是什么?](http://stackoverflow.com/questions/4172722/what-is-the-rule-of-ree) –

回答

1

部分显示的代码至少有两个主要的错误。错误#1:

list<Car> train; 

// ... 

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

这是object slicing一个教科书案例。 trainCar s的std::list。显示的代码构造一个ChairCar,并将其放入列表中。这将切掉ChairCar子类,并将Car超类复制到列表中。

Bug#2是这里的主要bug:这个类violates the Rule Of Three。明确的delete的动态范围构造的类成员。但是,Car类没有定义复制构造函数,也没有定义赋值运算符。这几乎排除了该课程符合三级规则的可能性。

因此,这两个错误会导致致命的组合。在初始对象切片期间,暂时的ChairCar对象被破坏,但是只有在其超类的副本被拷贝构建到列表的容器中之后才会被销毁。作为销毁的一部分,Car的析构函数delete是其动态范围的类成员。

然后,最终,列表容器被销毁,列表中被切掉的Car被破坏,并且其析构函数尝试到delete指针,该指针已经是delete d。

游戏结束。