析构函数问题+列表显示[重复]

Posted

技术标签:

【中文标题】析构函数问题+列表显示[重复]【英文标题】:Destructor problems+ list display [duplicate] 【发布时间】:2016-02-07 00:05:30 【问题描述】:

我有以下代码: 问题是当我在 main 类型中创建一个列表时:Reteta。 显示列表后,我收到错误分配错误。如果我从 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 
    

【问题讨论】:

Medicament operator=(Medicament x) 赋值运算符应该返回一个引用,而不是一个新对象。为什么不使用std::string 而不是char *?单独这样做会削减您编写的代码的主要部分。 我是新手。我必须这样做。几周后我将只玩 STL。 应该是相反的。现在使用 STL,稍后使用指针(很久以后)。 当您的类在构造函数中分配内存并在析构函数中释放内存时,您必须正确实现复制构造函数和复制赋值运算符。 嗯..您使用的是std::list而不是std::string?说真的,如果您使用 std::string 而不是 char *std::vector&lt;Medicament&gt; 而不是 new Medicament[n],那么所有这些代码都可以工作。 【参考方案1】:

这是内存覆盖:

    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 类编写赋值运算符、复制构造函数或析构函数。


另一个错误是您的Reteta 类缺少复制构造函数和赋值运算符,因此由于Medicament* 成员,它不能安全地复制。然后,您将此类用作std::list&lt;Reteta&gt; 中的类型。

由于Reteta 不能安全地复制,而std::list 进行复制,因此您进入了未定义行为的世界。因此,您必须为Reteta 类提供适当的复制/赋值运算符。

【讨论】:

责备我的老师 :)) 在 30 小时内我在 PO 进行了期末考试。所以我们不得不使用 *char 等。STL 就像考试的 10%。那么错误是什么?如果我从 Reteta 类中删除析构函数,它就可以工作.. 第 116 行和第 265 行是问题 “由于 Reteta 不是安全可复制的,并且 std::list 进行复制,因此您进入了未定义行为的世界。因此您必须为 Reteta 类提供适当的复制/赋值运算符。”这是我的问题。我创建了这些运算符并开始工作。谢谢你的时间保罗!

以上是关于析构函数问题+列表显示[重复]的主要内容,如果未能解决你的问题,请参考以下文章

使用使析构函数私有[重复]

ccombobox析构函数会自动清空列表框吗

C ++中的析构函数调用顺序[重复]

构造函数/析构函数计数不匹配[重复]

构造函数和析构函数中的虚函数调用[重复]

c ++的构造函数和析构函数汇编[重复]