0

I am using friend classes and I want to use rec's destructor when I call DeleteItem from my list class. However, there is a pointer pointing to the record that I want to delete, so I do not know how to call the destructor so it will do what I want. Classes:

   class rec
    {
           friend class list;
       private:
           char * id;
           char firstname[15];
           char lastname[15];
           int ar[10];
           rec* prev;
           rec* next;
       public:
           void SetData ( char * id_in, char * fn, char * ln, int * ans_in);
                rec( char *i, char *fn, char *ln, int *a);
                rec();
           void operator= (const rec& r);
                rec (const rec& r);
           void Print();
               ~rec();
    };

    class list
    {
      private:
          rec* first;
          rec* last;
      public:
          int AddItem(rec r);
          int DeleteItem (char* delid);
          void PrintList( int order);
          int ReadData(char *inanswer, char *inkey);
          int WriteData(char *answer, char *key);
              list();
          void operator= (list l);
      private:
          int CheckDuplicate(rec r);
          void DeleteData();
          int Count(char *filename);
    };

~rec()

        rec :: ~rec()
{
  if (id != NULL)
    {
      delete [] id;
    }
}

DeleteItem (Snipet)

int list :: DeleteItem(char *delid)     
{
    int id_counter;
        rec *current = first;
        while (current || current == NULL)
          {
            if (current == NULL)
              {
                return 0;
              }
            else
              {
                id_counter = strcmp(current -> id, delid);            
                 if (id_counter != 0)
                   {
                     current = current -> next;
                   }
                 else
                   {
                     if (current == first && current != last)        
                       {
                         ~rec();          //Here
                         first = current -> next;
                         delete current;
                         first -> prev = NULL;
                         return 1;
                       }

Delete item will compile fine if I manually put in delete[] current ->id; but does this when I try to compile as is

list.cpp:292: error: no match for ‘operator~’ in ‘~rec()’
/usr/lib/gcc/x86_64-redhat-linux/4.3.0/../../../../include/c++/4.3.0/bits/ios_base.h:105: note: candidates are: std::_Ios_Fmtflags std::operator~(std::_Ios_Fmtflags)
/usr/lib/gcc/x86_64-redhat-linux/4.3.0/../../../../include/c++/4.3.0/bits/ios_base.h:145: note:                 std::_Ios_Openmode std::operator~(std::_Ios_Openmode)
/usr/lib/gcc/x86_64-redhat-linux/4.3.0/../../../../include/c++/4.3.0/bits/ios_base.h:183: note:                 std::_Ios_Iostate std::operator~(std::_Ios_Iostate)

Is it my destructor that needs to be fixed or is it something to do in DeleteItem?

  • Please format your code properly to be readable here. –  Apr 15 '17 at 16:19
  • You consider to solve your problem without "friend", because it's bad habit – 21koizyd Apr 15 '17 at 16:21
  • 4
    You should almost never call a destructor explicitly. Certainly not for this class. You should also avoid raw pointers and arrays. Use std::string, std::vector and std::shared_ptr/std::unique_ptr instead. – n. m. could be an AI Apr 15 '17 at 16:22
  • What do you mean exactly, 21koizyd? I am quite new to this objective wat of programming – Penny Allison Apr 15 '17 at 16:22
  • in this case, I need to call it explicitly and am having a lot of problems doing so – Penny Allison Apr 15 '17 at 16:26
  • @n.m. OP looks to be reimplementing `std::deque` here – Caleth Apr 15 '17 at 16:49
  • "I need to call it explicitly" What makes you think so? – n. m. could be an AI Apr 15 '17 at 16:59
  • @Caleth looks like an intrusive lonked list to me. – n. m. could be an AI Apr 15 '17 at 17:03
  • @21koizyd: Using the `friend` keyword is a better alternative than unnecessarily exposing a public interface. – aschepler Apr 15 '17 at 17:18
  • 1. To destroy object `x`, you should use `delete x;` but only if it was dynamically allocated with `new`. `delete x;` will automatically call `x`'s destructor. You look to already be doing this a few lines later. 2. non-static member functions must be invoked on an instance of the class. `~rec` would have to be called something like `current->~rec();`, but per point 1 you will almost never need to do this. – user4581301 Apr 15 '17 at 17:18

1 Answers1

2

To call a destructor, the syntax is current->~rec(), but in almost cases, you shouldn't call directly a destructor in C++. By calling delete current, the C++ will automatically call the destructor before de-allocating its memory.

In your case, as you are also using delete after calling ~rec(), your destructor will be called twice, so you will result to a double free corruption as your constructor is trying to free id memory.

Advice: To avoid using friend class, in your case, next and prev members are related to the list, and not to rec class. So your list class could have a nested decorator class that will wrap your rec class like:

class list
{
    struct item {
        rec* value;
        rec* prev;
        rec* next;
    };
    item * first;
    item * last;
public:
    // ...
};

Then the logic of your list will be well isolated from the logic of your rec class.

Nikazo
  • 57
  • 4