异常未处理的违规访问

时间:2020-05-23 02:57:03

标签: c++ visual-studio

我正在使用动态数组在函数assignbook中对其进行扩展,但我不知道为什么当我delete[]数组时会给我未处理的访问冲突。

这是主要的

int main() {
    Translator t;
    Book b;
    t.AssignBook(b);
    t.AssignBook(b);
    t.AssignBook(b);
    t.AssignBook(b);
    t.AssignBook(b);
    t.AssignBook(b);
    t.AssignBook(b);
    t.AssignBook(b);
    t.AssignBook(b);
    t.AssignBook(b);
    t.AssignBook(b);
    t.AssignBook(b);
    cout << t.getNumBooks();
}

这是翻译器类的实现:

void Translator::AssignBook(Book& x) {
    if (numBooks < size) {
        translatebooks[numBooks] = x;
        numBooks++;
    }
    else {
        size += 10;
        Book* t = new Book[size];
        for (int i = 0; i < numBooks; i++) {
            t[i] = translatebooks[i];
        }
        delete[] translatebooks;
        translatebooks = t;
        translatebooks[numBooks] = x;
        cout << "The array is too small so it expanded from size " << numBooks << " to " << size << endl;
        numBooks++;
    }
}

这是错误:

the error of the debugger

此错误已解决,请帮忙。我确实在析构函数中再次删除了数组。

当我删除delete[]语句时,它可以工作,但仍然给我带来奇怪的访问权限。 :/

有完整的代码:

#include<iostream>
#include<string>

#define size1 2

using namespace std;

class Date {
private:
    int Day;
    int Month;
    int Year;


public:
    Date();
    Date(int, int, int);
    int getDay() const;
    int getMonth() const;
    int getYear() const;
    void setDate(int, int, int);
    void setMonth(int);
    void setYear(int);
    void setDay(int);
    void print() const;
};

class Person {
private :
    int PID;
    string Pname;

public :
    Person();
    Person(int, string);
    int getPID() const;
    string getPname() const;
    void setPID(int);
    void setPerson(int, string);
    void setPname(string);
    void print() const;
};

class Book {
private:
    int ISBN;
    string BookTitle;
    int NumPages;
    string Language;
    Date PublishingDate;
    int NumAuthors;
    Person* Authors;
public:
    Book();
    Book(int, string, int, string, Date&, int);
    ~Book();
    void setISBN(int);
    void setBookTitle(string);
    void setLanguage(string);
    void setNumPages(int);
    void setPublishDate(Date&);
    void setNumberAuthors(int);
    void setAuthor(Person&);
    int getISBN() const;
    string getBookTitle() const;
    string getLanguage() const;
    int getNumPages() const;
    Date getPublishDate() const;
    int getNumberAuthors() const;
    void print() const;
};

class Employee {
private:
    Person Ename;
    double salary;

protected:
    int Rank;

public:
    Employee();
    Employee(Person&, double ,int);
    void setEname(Person&);
    void setSalary(double);
    void setRank(int);
    Person getEname() const;
    int getRank() const;
    virtual bool isManager() ;
    virtual double getNetSalary();
    double getSalary() const;
    void print() const;
    virtual void AssignBook(Book&);
};

class Translator:public Employee{
private:
    int Experience;
    int numBooks;
    Book *translatebooks;
    int size;
public :
    void setExperience(int);
    void AssignBook(Book&);
    void unAssignBook(int ISBN);
    double getNetSalary() const;
    int getExperience() const;
    int getNumBooks() const;
    Translator();
    Translator(Person&, double, int,int);
    ~Translator();
    bool isManager();
    void print() const;
};

class Manager : public Employee {
private:
    bool certified;

public :
    void setCertified(bool x);
    bool getCertified();
    Manager();
    Manager(Person&, double, int,bool);
    ~Manager();
    bool isManager();
};

Employee* ReadOneEmployee() {
    int x;
    cout << "Please Enter 1 for Translator \n 2 for Manager\n";
    cin >> x;
    if (x == 1) {
        cout << "Name :" << endl;
        string name;
        cin >> name;
        cout << "Rank: \n";
        int Rank;
        cin >> Rank;
        cout << "Experience\n";
        int Experience;
        cin >> Experience;
        cout << "Salary \n";
        double salary;
        cin >> salary;
        cout << "ID =\n";
            int ID;
        cin >> ID;
        Person P(ID, name);
        return new Translator(P, salary, Rank, Experience);
    }
    else if (x == 2) {
        cout << "Name :" << endl;
        string name;
        cin >> name;
        cout << "Rank: \n";
        int Rank;
        cin >> Rank;
        cout << "Certified:\n";
        bool Experience;
        cin >> Experience;
        cout << "Salary \n";
        double salary;
        cin >> salary;
        cout << "ID =\n";
        int ID;
        cin >> ID;
        Person P(ID, name);
        return new Manager(P, salary, Rank, Experience);
    }
}

double Tax = 0.2;

int main() {
    Book books[200];
    Person z(2,"Meh");
    Person x(2, "xd");
    books[0].setAuthor(z);
    books[0].setAuthor(x);
    books[0].setNumPages(5);
    Employee *list[size1];
    for (int i = 0; i < size1; i++) {
        list[i] = ReadOneEmployee();
    }
    int booksnum = 123;
    int i = 0;
    while (booksnum >= 0) {
        if (!list[i]->isManager() && i<size1) {
            list[i]->AssignBook(books[booksnum]);
            i++;
        }
        else if (i >= size1) {
            i = 0;
        }
        booksnum--;
    }
    for (int i = 0; i < size1; i++) {
        cout << "Name :" << list[i]->getEname().getPname() << endl;
        cout << "Salary =" << list[i]->getSalary() << endl;
        cout << "Net Salary =" << list[i]->getNetSalary() << endl;
    }
    double totalN = 0,totalS=0;
    for (int i = 0; i < size1; i++) {
        totalN += list[i]->getNetSalary();
        totalS += list[i]->getSalary();
    }
    cout << "Total  Salary is :" << totalS << endl;
    cout << "Total Net Salary is :" << totalN << endl;

    int totalP = 0;
    for (int i = 0; i < 200; i++) {
        totalP += books[i].getNumPages();
    }
    cout << "Total  Pages is :" << totalP << endl;
    int max = 0;
    for (int i = 0; i < 200; i++) {
        if (books[i].getNumberAuthors() > max) {
            max = books[i].getNumberAuthors();
        }
    }
    for (int i = 0; i < 200; i++) {
        if (books[i].getNumberAuthors() == max) {
            books[i].print();
        }
    }
}

//i used regions to make it easier to read!
#pragma region Date_Implementation
Date::Date() {
    Day = Month = 1;
    Year = 1900;
}

Date::Date(int x,int y,int z) {
    setDate(x, y, z);
}

int Date::getDay() const {
    return Day;
}

int Date::getMonth() const {
    return Month;
}

int Date::getYear() const {
    return Year;
}

void Date::setDate(int x, int y, int z) {
    setDay(x);
    setMonth(y);
    setYear(z);
}

void Date::setMonth(int x) {
    if (x > 0 && x <= 12) {
    Month = x;
    }
    else {
        cout << "Invalid Value for the Months and it's been set to 1\n";
        Month = 1;
    }
}

void Date::setYear(int x){
    if (x >= 1900) {
        Year = x;
    }
    else {
        cout << "Invalid Value for the Years and it's been set to 1900\n";
        Year = 1900;
    }
}

void Date::setDay(int x) {
    if (x > 0 && x <= 31) {
        Day = x;
    }
    else {
        cout << "Invalid Value for the Days and it's been set to 1\n";
        Day = 1;
    }
}

void Date::print() const {
    cout << "The Date is: " << Day << "/" << Month << "/" << Year << endl;
}
#pragma endregion

#pragma region Person_Implemntation
Person::Person() {
    Pname = "";
    PID = 1;
}

Person::Person(int x, string y) {
    setPerson(x, y);
}

void Person ::setPerson(int x, string y) {
    setPname(y);
    setPID(x);
}

int Person::getPID() const {
    return PID;
}

string Person::getPname() const {
    return Pname;
}

void Person::setPID(int x) {
    if (x > 0) {
        PID = x;
    }
    else {
        cout << "Invalid Value for PID it's been set to 1\n";
        PID = 1;
    }
}

void Person::setPname(string x) {

    if (x != "") {
        Pname = x;
    }
    else {
        cout << "Invalid Value for Pname it's been set to \"\"\n";
        Pname="";
    }
}

void Person::print() const {
    cout << "Person's name = " << Pname << endl;
    cout << "Person's ID = " << PID << endl;
}
#pragma endregion

#pragma region Book_Implementation
Book::Book() {
    ISBN = NumPages = 1;
    Authors = new Person[3];
    BookTitle = "";
    Language = "English";
    NumAuthors = 0;
    PublishingDate.setDate(1, 1, 1900);
}

Book::Book(int x, string y, int z, string c, Date& v, int b) {
    setISBN(x);
    setBookTitle(y);
    setNumPages(z);
    setLanguage(c);
    setPublishDate(v);
    NumAuthors = 0;
}

Book::~Book() {
//  cout << "Book " << BookTitle << " Destructed\n";
    delete[] Authors;
}

void Book::setISBN(int x) {
    if (x > 0) {
        ISBN = x;
    }
    else {
        cout << "Invalid Value for ISBN it's been set to 1\n";
        ISBN = 1;
    }
}

void Book::setBookTitle(string x) {
    if (x != "") {
        BookTitle = x;
    }
    else {
        cout << "Invalid value for Book title it's been set to \"\"\n";
        BookTitle = "";
    }
}

void Book::setLanguage(string x) {
    if (x == "English" ||x=="Arabic") {
        BookTitle = x;
    }
    else {
        cout << "Invalid value for Book's Language it's been set to English\n";
        BookTitle = "English";
    }
}

void Book::setNumPages(int x) {
    if (x > 0) {
        NumPages = x;
    }
    else {
        cout << "Invalid Value for Number of Pages it's been set to 1\n";
        NumPages = 1;
    }
}

void Book::setPublishDate(Date& x) {
    PublishingDate.setDate(x.getDay(), x.getMonth(), x.getYear());
}
void Book::setNumberAuthors(int x) {
    if (x > 0 && x<=3) {
        NumAuthors = x;
    }
    else {
        cout << "Invalid Value for Number of authors it's been set to 1\n";
        NumAuthors = 1;
    }
}

void Book::setAuthor(Person& x) {
    if (NumAuthors < 3) {
        Authors[NumAuthors].setPerson(x.getPID(), x.getPname());
        NumAuthors++;
    }
    else cout << "Can't set an author cause the array is full!!\n";
}

int Book::getISBN() const {
    return ISBN;
}

string Book::getBookTitle() const {
    return BookTitle;
}

int Book::getNumPages() const {
    return NumPages;
}

Date Book::getPublishDate() const {
    return PublishingDate;
}

int Book::getNumberAuthors() const {
    return NumAuthors;
}

string Book::getLanguage() const {
    return Language;
}

void Book::print() const {
    cout << "ISBN = " << ISBN << endl;
    cout << "BookTitle = " << BookTitle << endl;
    cout << "Number of Pages = " << NumPages << endl;
    cout << "Language = " << Language << endl;
    cout << "The Authors that were set :\n";
    for (int i = 0; i < NumAuthors; i++) {
        Authors[i].print();
    }
}
#pragma endregion

#pragma region Employee_Implementation
Employee::Employee() {
    Rank = salary = 0;
    Ename.setPerson(1, "Default");
}

Employee::Employee(Person& x, double y, int z) {
    setEname(x);
    setRank(z);
    setSalary(y);
}

void Employee::setEname(Person& x) {
    Ename.setPerson(x.getPID(), x.getPname());
}

void Employee::setSalary(double x) {
    if (x > 0) {
        salary = x;
    }
    else {
        cout << "Invalid Value for Salary it's been set to 0\n";
        salary = 0;
    }
}

void Employee::setRank(int x) {
    if (x >= 0) {
        Rank = x;
    }
    else {
        cout << "Invalid Value for Rank it's been set to 0\n";
        Rank = 0;
    }
}

Person Employee::getEname() const {
    return Ename;
}

int Employee::getRank() const {
    return Rank;
}

double Employee::getSalary() const {
    return salary;
}

double Employee::getNetSalary() {
    double totalS = salary + (Rank * 320);
    double Net_Salary = totalS - totalS * Tax;
    return Net_Salary;
}

void Employee::print() const {
    Ename.print();
    cout << "Rank = " << Rank<<endl;
    cout << "salary = " << salary << endl;
}

bool Employee :: isManager() {
    return false;
}

void Employee::AssignBook(Book& x) {
    cout << "Can't cause it's just an Employee!";
}
#pragma endregion

#pragma region Translator_Implementation
void Translator::setExperience(int x) {
    if (x >= 0) {
        Experience = x;
    }
    else
    {
        cout << "Invalid Value for The Experience it's been set to 0\n";
        Experience = 0;
    }
}

void Translator::AssignBook(Book& x) {
    if (numBooks < size) {
        translatebooks[numBooks] = x;
        numBooks++;
    }
    else {
        size += 10;
        Book* t = new Book[size];
        for (int i = 0; i < numBooks; i++) {
            t[i] = translatebooks[i];
        }
        delete[] translatebooks;
        translatebooks = t;
        translatebooks[numBooks] = x;
        cout << "The array is too small so it expanded from size " << numBooks << " to " << size << endl;
        numBooks++;
    }
}

void Translator::unAssignBook(int ISBN) {
    for (int i = 0; i < numBooks; i++) {
        if (translatebooks[i].getISBN() == ISBN) {
            for (int j = i; j < numBooks-1; j++) {
                translatebooks[j] = translatebooks[j + 1];
            }
            numBooks--;
            break;
        }
    }
}

double Translator::getNetSalary() const {
    int total = 1;
    for (int i = 0; i < numBooks; i++) {
        total += translatebooks[i].getNumPages();
    }
    return getNetSalary() + 5 * total;
}

int Translator::getExperience() const {
    return Experience;
}

int Translator::getNumBooks() const {
    return numBooks;
}

Translator::Translator():Employee() {
    Experience = 0;
    numBooks = 0;
    size = 10;
    translatebooks = new Book[size];
}

Translator::Translator(Person& x, double y, int z, int c) :Employee(x, y, z) {
    setExperience(c);
    numBooks = 0;
    size = 10;
    translatebooks = new Book[size];
}

Translator::~Translator() {
    delete[] translatebooks;
    translatebooks = NULL;
}

bool Translator:: isManager() {
    return false;
}

void Translator::print() const{
    Employee::print();
    cout << "Experience = " << Experience << endl;
    cout << "Number of books = " << numBooks << endl;
    cout << "And they are :\n";
    if (numBooks == 0) cout << "None\n";
    else
    for (int i = 0; i < numBooks; i++) {
        translatebooks[i].print();
    }
}
#pragma endregion

#pragma region Manger_Implementation
void Manager::setCertified(bool x) {
    certified = x;
}

bool Manager::getCertified() {
    return certified;
}

Manager::Manager():Employee() {
    certified = false;
}

Manager::Manager(Person& x, double y , int z, bool c):Employee(x,y,z) {
    certified = c;
}

Manager::~Manager() {
    cout << "Manager Destructed\n";
}

bool Manager::isManager() {
    return true;
}
#pragma endregion

1 个答案:

答案 0 :(得分:1)

您有违反0/3/5的规则。您没有Book的副本构造函数。因此,当您的代码这样做时:

    for (int i = 0; i < numBooks; i++) {
        t[i] = translatebooks[i];
   }

这将为Book调用 default 复制构造函数。这是一场灾难,因为析构函数如下所示:

Book::~Book() {
//  cout << "Book " << BookTitle << " Destructed\n";
    delete[] Authors;
}

因此,默认的复制构造函数为Book的两个Authors对象赋予相同的值。首先销毁的那个都将其删除。这样就使另一个指针无处指向。

然后在扩展数组时运行以下代码:

  delete[] translatebooks;

这会破坏您复制的书籍,并破坏副本中的Authors阵列。

道德:不要使用原始指针。不要使用原始数组。我们有很多使所有这些东西变得容易的类,为什么要使其变得困难呢?