析构函数问题+列表展示

Destructor problems+ list display

我有以下代码: 问题是当我在主要类型中创建列表时:Reteta。 显示列表后,我收到错误分配错误。如果我从 class Reteta 注释析构函数,程序就会运行。你能帮我找到错误吗?或者也许我没有很好地显示列表,所以程序还有其他问题需要处理。 这是代码:

#include<iostream>
#include<fstream>
#include<list>
using namespace std;

class Medicament{
private:
    char *denumire;
    float pret;
public:
    Medicament()
    {
        this->pret = 0;
        this->denumire = new char[strlen("Fara denumire")];
        strcpy(this->denumire, "Fara denumire");
    }
    Medicament(char* denumire, float pret)
    {
        this->denumire = new char[strlen(denumire) + 1];
        strcpy(this->denumire, denumire);
        this->pret = pret;
    }
    Medicament(const Medicament& x)
    {
        this->denumire = new char[strlen(x.denumire) + 1];
        strcpy(this->denumire, x.denumire);
        this->pret = x.pret;
    }
    ~Medicament()
    {
        if (this->denumire)
        {
            delete[] this->denumire;
        }
    }
    void setDenumire(char *x)
    {
        if (x)
        {
            if (this->denumire)
            {
                delete[] this->denumire;
            }
            this->denumire = new char[strlen(x) + 1];
            strcpy(this->denumire, x);
        }
    }
    char* getDenumire()
    {
        return this->denumire;
    }
    void setPret(float f)
    {
        if (f)
        {
            this->pret = f;
        }
    }
    Medicament operator=(Medicament x)
    {
        this->denumire = new char[strlen(x.denumire) + 1];
        strcpy(this->denumire, x.denumire);
        this->pret = x.pret;
        return *this;
    }
    friend ostream& operator<<(ostream& consola, Medicament &x)
    {
        consola << "Medicament: " << x.denumire << endl; //error here
        consola << "Pret: " << x.pret << endl;
        return consola;
    }
    float getPret()
    {
        return this->pret;
    }
    friend class Reteta;
};

class Reteta{
protected:
    Medicament *medicamente;
    int n;
public:
    Reteta()
    {
        this->n = 0;
        this->medicamente = NULL;
    }
    Reteta(Medicament *v, int n)
    {
        this->n = n;
        this->medicamente = new Medicament[n];
        for (int i = 0; i < n; i++)
        {
            this->medicamente[i] = v[i];
        }
    }
    ~Reteta()
    {
        if (this->medicamente)
        {
            delete[] this->medicamente;   //The problem is here. If I comment this the program works.
        }
    }
    int getN()
    {
        return this->n;
    }

    friend ostream& operator<<(ostream& consola, Reteta& x)
    {
        consola << "Numar de medicamente: " << x.n << endl;
        consola << "    -->Lista Medicamente<-- "<<endl;
        for (int i = 0; i < x.n; i++)
        {
            consola << x.medicamente[i].getDenumire() <<endl; //error at this line when I compile
            consola << x.medicamente[i].getPret()<< endl;

        }
        return consola;
    }
    void adaugaMedicament(Medicament x)
    {
        Reteta y;
        y.medicamente= new Medicament[this->n+1];
        for (int i = 0; i < this->n; i++)
        {
            y.medicamente[i] = this->medicamente[i];
        }
        y.medicamente[this->n] = x;
        delete[] this->medicamente;
        this->medicamente = new Medicament[this->n + 1];
        this->n++;
        for (int i = 0; i < this->n; i++)
        {
            this->medicamente[i] = y.medicamente[i];
        }
    }
    Medicament operator[](int i)
    {
        if (i >= 0 && i < this->n)
        {
            return this->medicamente[i];
        }
    }
    friend class RetetaCompensata;
    virtual float getValoare()
    {
        float sum = 0;
        for (int i = 0; i < this->n; i++)
        {
            sum=sum+this->medicamente[i].getPret();
        }
        return sum;
    }
    friend ifstream& operator>>(ifstream& consola, Reteta& x)
    {
        char aux[30];
        float z;
        consola >> x.n;
        if (x.medicamente)
            delete[] x.medicamente;
        x.medicamente = new Medicament[x.n];
        for (int i = 0; i < x.n; i++)
        {
            consola >> aux >> z;
            Medicament m(aux, z);
            x.medicamente[i] = m;
        }
        return consola;
    }
};

class RetetaCompensata : public Reteta{
private:
    float procentCompensat;
public:
    RetetaCompensata(float procent)
    {
        this->procentCompensat = procent;
    }
    RetetaCompensata(Reteta r, float procent)
    {

        this->procentCompensat = procent;
        this->n = r.n;
        this->medicamente = new Medicament[r.n];
        for (int i = 0; i < r.n; i++)
        {
            this->medicamente[i] = r.medicamente[i];
        }
    }
    float getValoare()
    {
        float sum = 0;
        sum = this->procentCompensat*this->getValoare();
        return sum;
    }

    friend ostream& operator<<(ostream& consola, RetetaCompensata &x)
    {
        consola << "**Procent compensat: " << x.procentCompensat << endl;
        consola << "Numar de medicamente: " << x.n << endl;
        consola << "    -->Lista Medicamente<-- " << endl;
        for (int i = 0; i < x.n; i++)
        {
            consola << x.medicamente[i] << " ";
        }
        return consola;
    }
};

void main()
{
    //1
    Medicament nurofen("Nurofen", 11.25f);
    Medicament aspirina = nurofen;
    aspirina.setDenumire("Aspirina");
    aspirina.setPret(4.5f);
    Medicament bixtonim("Bixtonim", 8.2f);
    Medicament temp;
    temp = nurofen;
    cout << temp << endl;
    cout << nurofen << endl;
    cout << aspirina << endl;
    //2
    Medicament medicamente[] = { aspirina, nurofen };
    Reteta r0(medicamente, 2);
    cout << r0 << endl;
    //3
    Reteta r1;
    r1.adaugaMedicament(nurofen);
    r1.adaugaMedicament(aspirina);
    for (int i = 0; i < r1.getN(); i++)
    {
        cout << r1[i] << endl;
    }
    //4
    RetetaCompensata r2(0.5);
    r2.adaugaMedicament(bixtonim);
    r2.adaugaMedicament(aspirina);


    RetetaCompensata r3(r1, 0.2);
    cout << "AFISARE R3" << endl;
    cout << r3 << endl << endl;
    Reteta* p = &r1;
    cout <<"Valoare reteta r1: "<< p->getValoare() << endl;
    //5
    Reteta r4;
    ifstream fisier("retete.txt");
    fisier >> r4;
    cout << r4 << endl;
    //6
    cout << endl << "Afisare Lista :" << endl << endl << endl;
    list<Reteta> R;
    list<Reteta>::iterator it;
    R.push_back(r0);
    R.push_back(r1);
    R.push_back(r3);
    R.push_back(r2);
    R.push_back(r4);
    for (it = R.begin(); it != R.end(); it++)
    {
        cout << *it << "  Valoare Reteta: " << it->getValoare() << endl << endl << endl; // error at this line when I compile 
    }
}

这是内存覆盖:

    this->denumire = new char[strlen("Fara denumire")];
    strcpy(this->denumire, "Fara denumire");

您没有为终止空字符分配空间:

    this->denumire = new char[strlen("Fara denumire") + 1];
    strcpy(this->denumire, "Fara denumire");

但是,当您有 std::string 可用时,为什么要这样做呢?仅此一项不仅可以减轻此类错误,而且您无需为 Medicament class.

编写赋值运算符、复制构造函数或析构函数

另一个错误是您的 Reteta class 缺少复制构造函数和赋值运算符,因此由于 Medicament* 成员,它无法安全复制。然后您将此 class 用作 std::list<Reteta> 中的类型。

由于 Reteta 不可安全复制,而 std::list 进行复制,您进入了未定义行为的世界。因此,您必须为 Reteta class.

提供适当的复制/赋值运算符