0

A program that stores a phone company's consumers data in a linked list. At the end it displays the bill for each human. I have the following codes:

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

Client's class:

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

};

I read the data from 2 files. First file contains the name, phone number, type of contract. Second file contains the phone number, talked minutes and sent 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;
}

And the main:

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

My problem that I should free the allocated memory but I got on idea how. Which class' destructor should do the dirty job. I would appreciate if someone could use my code, to show how the "destructor inheritance" works.

Sorry for my bad english and thanks for the help. This site helped me alot of times, but for this problem I did not find a solution.

Melvin
  • 1
  • 2
  • Use [`std::shared_ptr`](http://en.cppreference.com/w/cpp/memory/shared_ptr) (and potentially [`std::dynamic_ptr_cast`](http://en.cppreference.com/w/cpp/memory/shared_ptr/pointer_cast)), it'll take care of the cleanup for you – hlt May 13 '18 at 10:44
  • It looks really complicated. Is not there a way to just make the destructors? I would like to not change the code, after I could make it work... – Melvin May 13 '18 at 10:49
  • Use containers and smart pointers, not raw `new`/`delete`. – Jesper Juhl May 13 '18 at 10:56
  • Can you show me in my code, how am I supposed to use these smart pointers? I would like to not use stl containers, although it would be much simpler. – Melvin May 13 '18 at 11:23

1 Answers1

1

If you have a pointer BaseTypeOfContract* typeOfContract; that is used to point to different derived classes, then BaseTypeOfContract needs to have a virtual destructor for delete typeOfContract to work.

And as Client seems to create the objects pointed to, it also ought to be responsible for cleaning them up. Either by using delete typeOfContract; in its destructor, or by storing a smart pointer to get the work done automatically.

The other part is that each Client stores a pointer to the next Client. That seems like not the best design. In real life it is not at all like each person knowing who is the next person that buys a cell phone in the same store. :-)

You would be much better of with a container, like std::vector<Client>, that would also handle the lifetime of the Client objects.

Bo Persson
  • 90,663
  • 31
  • 146
  • 203
  • Using delete how? Like: delete this->typeOfContract; delete this; ? – Melvin May 13 '18 at 10:54
  • Yes, if you do `something = new x;` you need a `delete something`in the proper place to release the object again. – Bo Persson May 13 '18 at 10:58
  • 2
    @Melvin In 99.9% of all cases `delete this;` would be a bug. – Jesper Juhl May 13 '18 at 11:01
  • I'm trying to make the destructor but no success. Can someone fix my code maybe? Would be more understandable to see how it works well, than doing it randomly and at the end I am not even remembering which I tested... – Melvin May 13 '18 at 11:08
  • @Melvin Random experimentation is not a good way to learn programming. It's much better to follow a [good book](https://stackoverflow.com/q/388242/1782465) or good online tutorial. – Angew is no longer proud of SO May 13 '18 at 11:58
  • Sadly there is no any book that contains my code in a right way. – Melvin May 13 '18 at 12:12
  • @Melvin - Looking at your modeling (instead of the coding), we see that the function is called `preSetPlan`. Seem like you could then have a bunch of - eh... - preset plans, and just store a pointer or reference to the customers selected plan. Then there is no need to `new` anything. – Bo Persson May 13 '18 at 12:30