class destructure ...

Hi experts,

    I have a class as following :

 class Data
{
      private:
        Cat myCat ;
        Dog  myDog ;
   
     public :
       Data(Cat& aCat) ;
       Data(Dog& aDog) ;
       ~Data() ;      
       :
       :
} ;

Data::Data(Cat& aCat)
{
      myCat = aCat ;}
}

Data::Data(Dog& aDog)
{
     myDog = aDog;}

so how do I implement my ~Data() ? do I need to delete both myDog & myCat ?
or do I need two destructors ? or I should avoid this kind of codes ?

  many thanks !!!
LVL 1
meow00Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

AlexFMCommented:
You don't need to delete myCat and myDog in the destructor and currently destructor implementation should be empty.
Jaime OlivaresSoftware ArchitectCommented:
As a general rule, you have to delete (with 'delete' operator) what you have created using 'new' operator (dynamic creation). This is not the case.
mattjsimpsCommented:
You could even remove the

~Data();
line from the class definition, and rely on the default destructor, although it is good practice to provide your own even if it is empty.
Learn Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

meow00Author Commented:
thanks ... so what if :

 class Data
{
      private:
        Cat *myCats ;
        Dog  *myDogs ;
   
     public :
       Data(Cat* Cats) ;
       Data(Dog* Dogs) ;
       ~Data() ;      
       :
       :
} ;

Data::Data(Cat* Cats, int N)
{
      myCat = (Cat*)malloc(sizeof(Cat)*N) ;}
}

Data::Data(Dog*  Dogs, int N)
{
     myDog = (Dog*)malloc(sizeof(Dog)*N);}
}

 what should I do in the above case ??? many thanks !
mattjsimpsCommented:
You shouldn't be using malloc.

use new instead

In your destructor use delete[]
Jaime OlivaresSoftware ArchitectCommented:
The C++ way to dynamic allocation (as metioned previously):

 class Data
{
      private:
        Cat *myCats ;
        Dog  *myDogs ;
   
     public :
       Data(Cat* Cats) ;
       Data(Dog* Dogs) ;
       ~Data() ;      
       :
       :
} ;

Data::Data(Cat* Cats, int N)
{
      myCats = new Cat[N];
      myDogs = NULL;   // Always must be initialized to NULL, see why in destructor
}

Data::Data(Dog*  Dogs, int N)
{
     myDogs = new Dog[N];
     myCats = NULL;   // Always must be initialized to NULL, see why in destructor
}

Data::~Data()
{
     if (myCats)   // Delete only if it is not NULL
        delete [] myCat;
     if (myDogs)   // Delete only if it is not NULL
        delete [] myDog;
}
B1-66ERCommented:
if you using malloc, use function free() to  free allocated memory. In destructor then, you may write:

Data::~Data()
{
   free(myDog) ;
  free(myCat) ;
}
meow00Author Commented:
thanks very much !

However, I have problems using "new" because I am actually using some lib. (fftw)
It uses fftw_malloc() ... which corresponds to fftw_free() ...

in this case ... How do I do the following :
 if ("in" & "out" are allocated memory or not)
  --> if so ... I want to free it ...

please help ... many thanks...  

----------------------------------------------------------
     
     fftw_complex *in, *out ;

      in = (fftw_complex*)fftw_malloc(sizeof(fftw_complex)*WD*HT);
      out = (fftw_complex*)fftw_malloc(sizeof(fftw_complex)*WD*HT);

----------------------------------------
Jaime OlivaresSoftware ArchitectCommented:
Just but your fftw_free() calls into the destructor, assuming both are always allocated.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
ikeworkCommented:
hi meow,

the problem with c-style allocation/deallocation(malloc,free or the derivates in that lib) mixed with classes is, that no constructor/destructor is called. so if you do this:

Cat *pCat = new Cat;  // <<-- new calls the constructor of class "Cat" implicitely (malloc does not)
delete pCat; // <<-- delete calls the destructor of "Cat" implicitely (free does not)

if you use malloc and free(or your derivates) then only the memory for the class is allocated, but no constructor is called for that class. so if you have to use that kind of allocation, then you should provide Init()/Destroy() - memberfunctions in your Cat & Dog - classes which do the job, and call them after allocation(Init) and deallocation(Destroy)


class Cat
{
public :
      // both are never called, sionce you use your malloc/free-functions
      Cat() {}
      ~Cat() {}    

      // does the job of default-constructor
      void Init();
      // does the job of the destructor
      void Destroy();
} ;  

and in your Data-class

Data::Data(Cat* Cats, int N)
{
    myCat = (Cat*)malloc(sizeof(Cat)*N);

    // because no constructor is called by malloc, we need to initialize each object by ourselve with Cat::Init()
    for( int i = 0; i < N; ++i )
    {
        myCat[i].Init();
    }
}

and dont forget to call Destroy in each object before deallocation in destructor of Data.


hope it helps,
ike
ikeworkCommented:
another(cleaner) way is to overload the global "new" & "delete" functions or create new & delete only for specific classes(Cat & Dog) and call "fftw_malloc" and the corresponding free function from there. then you could simply use the c++-style new, which would call the constructor and destructor again. that would be the more cleaner way for c++.

here are some links for that found by google:

http://bdn.borland.com/article/0,1410,18041,00.html
http://www.devx.com/tips/Tip/5608
http://www.ozzu.com/ftopic21685.html


good luck,
ike
AxterCommented:
FYI:
Data::~Data()
{
     if (myCats)   // Delete only if it is not NULL
        delete [] myCat;
     if (myDogs)   // Delete only if it is not NULL
        delete [] myDog;
}

The above if condition is not needed IAW C++ standard.
You can just do the following:
Data::~Data()
{
     delete [] myCat;
     delete [] myDog;
}

IAW C++ standard, you can call the delete operator with a NULL value, and nothing happens.
That means the delete operator is already performming an IF condition to test for NULL.
There's  no need to perform this test yourself.
itsmeandnobodyelseCommented:
>>>> However, I have problems using "new" because I am actually using some lib. (fftw)
>>>> It uses fftw_malloc() ... which corresponds to fftw_free() ...

You can use 'new' and 'delete' for all your objects and fftw_malloc and fftw_free for all pointers created by library functions. Actually, most C++ compilers use a malloc to implement operator new.


>>>> Data::Data(Cat* Cats, int N)

Instead of fixed sized arrays, you could/should use a dynamic array like std::vector

#include <vector>
using namespace std;

class Data
{
     vector<Cat> myCats;
     vector<Dog> myDogs;
 
    public :
       Data(Cat* Cats, int N) : myCats(&Cats[0], &Cats[N]) {}
       
       Data(Dog* Dogs, int N) : myDogs(&Dogs[0], &Dogs[N]) {}
       Data(vector<Cat>& Cats) : myCats(Cats) {}
       Data(vector<Dog>& Dogs) : myDogs(Dogs) {}
       ~Data()  {}      
};

Note, in destructor all members were automatically deleted.

Regards, Alex
rstaveleyCommented:
Note that you can overload global operator new and delete to use your library allocator.

I've dummied your fftw_* functions in the following to prove the point. By setting DEMO to 0, you should make it use your library.

--------8<--------
//#include <iostream>
#include <cstdio>

#define      DEMO      1      // Set to zero in your environment

#ifdef DEMO
void *fftw_malloc(size_t size)
{
      void *p = malloc(size);

      // NB: Using fprintf because it doesn't use new/delete!

      //std::cerr << "Allocated " << size << " bytes at " << p << '\n';
      std::fprintf(stderr,"Allocated %u bytes at %p\n",size,p);

      return p;
}
void fftw_free(void *p)
{
        free(p);

      // NB: Using fprintf because it doesn't use new/delete!

      //std::cerr << "Freed " << p << '\n';
      std::fprintf(stderr,"Freed %p\n",p);
}
#endif

// Global operator new overload
inline void* ::operator new(size_t size)
{
      return fftw_malloc(size);
}

// Global operator delete overload
inline void ::operator delete(void* ptr)
{
        fftw_free(ptr);
}

class Cat {char c[100];};
class Dog {char c[1000];};

class Data
{
      Cat *catArr_;
      Dog *dogArr_;
public:
      Data(size_t CatCount,size_t DogCount);
       ~Data();
};

// Ctor
Data::Data(size_t CatCount,size_t DogCount)
      : catArr_(new Cat[CatCount])
      , dogArr_(new Dog[DogCount])
{
}

// Dtor
Data::~Data()
{
      delete [] catArr_;
      delete [] dogArr_;
}

int main()
{
      Data d(2,5);
}
--------8<---------
rstaveleyCommented:
Oops ... change that

#ifdef DEMO

to

#if DEMO

(Sorry)
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.