Должен ли быть виртуальный деструктор?Но как? - PullRequest
0 голосов
/ 13 мая 2018

Программа, которая сохраняет данные о потребителях телефонной компании в связанном списке. В конце он отображает счет за каждого человека. У меня есть следующие коды:

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 файлов. Первый файл содержит имя, номер телефона, тип договора. Второй файл содержит номер телефона, разговариваемые минуты и отправленное SMS.

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

Моя проблема в том, что я должен освободить выделенную память, но я понял, как. Деструктор какого класса должен делать грязную работу. Буду признателен, если кто-нибудь сможет использовать мой код, чтобы показать, как работает «наследование деструктора».

Извините за мой плохой английский и спасибо за помощь. Этот сайт помог мне много раз, но для этой проблемы я не нашел решения.

1 Ответ

0 голосов
/ 13 мая 2018

Если у вас есть указатель BaseTypeOfContract* typeOfContract;, который используется для указания на различные производные классы, тогда BaseTypeOfContract должен иметь виртуальный деструктор, чтобы delete typeOfContract работал.

И поскольку Client, кажется, создает указанные объекты, он также должен нести ответственность за их очистку. Либо используя delete typeOfContract; в своем деструкторе, либо сохраняя умный указатель для автоматического выполнения работы.

Другая часть состоит в том, что каждый Client хранит указатель на следующий Client. Это кажется не лучшим дизайном. В реальной жизни это совсем не то, что каждый человек знает, кто следующий, кто купит мобильный телефон в том же магазине. : -)

Вам будет намного лучше с контейнером, таким как std::vector<Client>, который также будет обрабатывать время жизни Client объектов.

...