【问题标题】:Should be a virtual destructor? But how?应该是虚拟析构函数?但是怎么做?
【发布时间】:2018-10-23 05:21:21
【问题描述】:

将电话公司的消费者数据存储在链接列表中的程序。最后,它显示每个人的账单。我有以下代码:

class BaseTypeOfContract
{
private:
   int minutePrice;
   int SMSPrice;
public:
    void setminutePrice(int x) { minutePrice = x; }
    void setSMSPrice(int x) { SMSPrice = x; }

    virtual int calculateBill(int talkedMinutes, int sentSMS) = 0;

    int getminutePrice() const { return minutePrice; }
    int getSMSPrice() const { return SMSPrice; }

};


class SMSBaseType : public BaseTypeOfContract
{
private:
   int freeSMS;
public:
   SMSBaseType(int minutePrice, int SMSPrice, int freeSMS)
   {
       setminutePrice(minutePrice);
       setSMSPrice(SMSPrice);
       setfreeSMS(freeSMS);
   }

public:

    void setfreeSMS(int free) { this->freeSMS = free; }

    virtual int calculateBill(int talkedMinutes, int sentSMS)
    {
        int billedSMS = (freeSMS > sentSMS) ? 0 : sentSMS - freeSMS;
        return talkedMinutes * getminutePrice() + billedSMS * getSMSPrice();
    }
};

class Base : public BaseTypeOfContract
{
public:
    Base()
    {
        setminutePrice(30);
        setSMSPrice(10);
    }
    virtual int calculateBill(int talkedMinutes, int sentSMS) { return talkedMinutes * getminutePrice() + sentSMS * getSMSPrice();}
};

class SMSMax : public SMSBaseType
{
public:
   SMSMax() : SMSBaseType(20, 5, 150) {}
};

class MobiNET: public SMSBaseType
{
public:
   MobiNET() : SMSBaseType(10, 15, 25) {}
};

客户类别:

class Client
{
public:
    std::string name;
    std::string phoneNumber;
    BaseTypeOfContract* typeOfContract;
    int talkedMinutes;
    int sentSMS;
    Client *next;
public:
    Client(){}
    Client(std::string n, std::string p, int bp, int ks) : name(n), phoneNumber(p), talkedMinutes(bp), sentSMS(ks) {}


    void preSetPlan(std::string s)
    {
        if (s == "MobiNET")
            this->typeOfContract = new MobiNET();
            else if (s == "SMSMax")
                this->typeOfContract = new SMSMax();
                else this->typeOfContract = new Base();
    }

    std::string getname() const { return name; }
    std::string getphoneNumber() const { return phoneNumber; }

    void setname(std::string n) { name = n; }
    void setphoneNumber(std::string pn) { phoneNumber = pn; }
    void settalkedMinutes(int bp) { talkedMinutes = bp; }
    void setsentSMS(int SSMS) { sentSMS = SSMS; }

    int getBill() const { return this->typeOfContract->calculateBill(talkedMinutes, sentSMS); }

};

我从 2 个文件中读取数据。第一个文件包含姓名、电话号码、合同类型。第二个文件包含电话号码、通话时间和发送的短信。

Client* file_read_in()
{
    std::ifstream ClientData;
    ClientData.open("clients.txt");

    Client *first = new Client;
    first = NULL;

    while (!ClientData.eof())
    {
        std::string name, phoneNumber, typeOfContract;
        ClientData >> name;
        ClientData >> phoneNumber;
        ClientData >> typeOfContract;

        std::ifstream ClientTalkedSent;
        ClientTalkedSent.open("used.txt");

        while(!ClientTalkedSent.eof())
        {
            std::string phoneNumber2;
            ClientTalkedSent >> phoneNumber2;

            if (phoneNumber2 == phoneNumber)
            {
                int talkedMinutes, sentSMS;
                ClientTalkedSent >> talkedMinutes;
                ClientTalkedSent >> sentSMS;

                Client* tmp = new Client(name, phoneNumber, talkedMinutes, sentSMS);
                tmp->preSetPlan(typeOfContract);
                tmp->next = NULL;

                if (first == NULL)
                {
                    first = tmp;
                }
                else
                {
                    Client *cond = first;
                    while (cond->next != NULL) cond = cond->next;
                    cond->next = tmp;
                }

            }
        }

        ClientTalkedSent.close();
    }
    ClientData.close();

    return first;
}

还有主要的:

int main()
{
    Client* first = file_read_in();

    while(first != NULL)
    {
        std::cout << first->getname() << " " << first->getphoneNumber() << " " << first->getBill() << std::endl;
        first = first->next;
    }

    return 0;
}

我的问题是我应该释放分配的内存,但我知道如何。哪个类的析构函数应该做脏活。如果有人可以使用我的代码来展示“析构函数继承”的工作原理,我将不胜感激。

对不起,我的英语不好,感谢您的帮助。这个网站帮助了我很多次,但是对于这个问题我没有找到解决方案。

【问题讨论】:

  • 使用std::shared_ptr(也可能是std::dynamic_ptr_cast),它会为您完成清理工作
  • 看起来很复杂。有没有办法只制作析构函数?在我可以让它工作之后,我不想更改代码......
  • 使用容器和智能指针,而不是原始的new/delete
  • 你能在我的代码中告诉我,我应该如何使用这些智能指针?我不想使用 stl 容器,虽然它会简单得多。

标签: c++ linked-list destructor


【解决方案1】:

如果你有一个指针BaseTypeOfContract* typeOfContract; 用于指向不同的派生类,那么BaseTypeOfContract 需要有一个虚拟析构函数delete typeOfContract 才能工作。

Client 似乎创建了指向的对象,它也应该负责清理它们。通过在其析构函数中使用delete typeOfContract;,或者通过存储智能指针来自动完成工作。

另一部分是每个Client 存储一个指向下一个Client 的指针。这似乎不是最好的设计。在现实生活中,根本不像每个人都知道谁是下一个在同一家商店购买手机的人。 :-)

如果使用std::vector&lt;Client&gt; 之类的容器会更好,它还可以处理Client 对象的生命周期。

【讨论】:

  • 如何使用delete?喜欢:删除this->typeOfContract;删除这个; ?
  • 是的,如果你这样做something = new x;,你需要一个delete something在适当的地方再次释放对象。
  • @Melvin 在 99.9% 的情况下,delete this; 是一个错误。
  • 我正在尝试制作析构函数但没有成功。有人可以修复我的代码吗?看看它是如何运作的会更容易理解,而不是随机做,最后我什至不记得我测试了哪个......
  • @Melvin 随机实验并不是学习编程的好方法。最好遵循good book 或好的在线教程。
猜你喜欢
  • 2016-12-23
  • 2015-11-12
  • 2010-11-10
  • 2011-03-31
  • 2012-04-18
  • 2011-04-07
  • 2020-11-24
  • 2010-09-22
相关资源
最近更新 更多