Thread: A virtual destructor dilema

  1. #1
    Registered User
    Join Date
    Jul 2008
    Posts
    14

    Question A virtual destructor dilema

    Hi,

    I'm trying to play with an abstract base class and 3 derived classes in a linked list.
    But when i began to design constructors and destructors for the classes i just hit a wall.

    So i'll simplify the code to be more relevant, wit just 1 derived class:

    Code:
    class Base        // abstract base class; no obj can be created for this class
    {
    protected:
          int bsnr;       
          char* bstxt;     //must be allocated with new & initialized
    public:
          Base() : bsnr(0)          // default constructor
          {
           bstxt = new char[size];   // allocation for a string of 'size' 
           strcpy(bstxt,  "smth");     // initialisation
           }
    X    virtual ~Base()=0   // virtual destructor, from what i read i can't give any definition here
          virtual func()=0     // pure virtual function
    };
    class Derived: public Base
    {
    protected:
           int drvnr;
           char* drvtxt;     // also mem allocation whit new
    pubilc:
           Derived() : drvnr(0)
           {
           bstxt = new char[size];   // allocation for a string of 'size' 
           strcpy(bstxt,  "smth");     // initialisation
           }
           ~Derived()
           {
     Y     delete[] drvtxt;
           }
            func(arg){ do something with bsnr, bstxt, drvnr, drvtxt, }
    };
    My question is where can I delete[] bstxt ?
    Am i allowed to do it in line X? like:
    Code:
    virtual ~Base()=0
    { delete[] bstxt; }
    or can I free memory for a Base member in a deriver class?
    Code:
    ~Derived()
           {
            delete[] bstxt;
            delete[] drvtxt;
           }
    Any hint or ideea is welcome.
    Thank you.

  2. #2
    The larch
    Join Date
    May 2006
    Posts
    3,573
    You should be able to provide implementation for the pure virtual destructor outside the class definition.

    However, since your Base class already contains another pure virtual method, there is no reason to make the destructor pure too: it takes only one pure method to make the whole class abstract.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  3. #3
    Registered User
    Join Date
    Jul 2008
    Posts
    14
    Quote Originally Posted by anon View Post
    it takes only one pure method to make the whole class abstract.
    i know that.

    The question is where can i use delete [] bstxt, in which destructor? Am I allowed to do it in the virtual destructor's definition in base class?
    I need the virtual destructor because i'll be doing lots of upcasting and downcasting later in the code.

  4. #4
    Registered User
    Join Date
    Apr 2008
    Posts
    890
    Quote Originally Posted by tzakieta View Post
    i know that.

    The question is where can i use delete [] bstxt, in which destructor?
    Why are you using a char[] instead of std::string?

    because i'll be doing lots of upcasting and downcasting later in the code.
    Then your code is likely ill-designed and should be refactored. Google for "Liskov Substitution Principle".

  5. #5
    Registered User
    Join Date
    Apr 2008
    Posts
    90
    You should do the cleanup of the Base class data in the Base destructor, and the Derived class data in the Derived class destructor.

    Currently, you have the Base destructor declared as a pure virtual function:

    Code:
    virtual ~Base()=0;
    It should be just a regular virtual function:

    Code:
    virtual ~Base();
    The difference is a pure virtual function does not have an implementation and therefore must be implemented in a derived class. A regular virtual function has an implementation and may be overridden by a derived class, but it doesn't have to be.

  6. #6
    Registered User
    Join Date
    Jul 2008
    Posts
    14
    So i'll simplify the code

    That's not my code. I wrote the code with headers and multiples cpp where i defined the functions I used.
    My problem is not the casting ( haven't got to it yet), but the use of the virtual destructor (especially te position) , so I posted a short ,"ill" & uncomplete code focused on my problem.

    I'll rephraze:
    Does an virtual destructor accept a declaration in the abstract base class?:
    Code:
    virtual ~Base()=0
    {
          delete[] str;       // str = new char[size]; in constructor.     
    };
    Last edited by tzakieta; 09-11-2008 at 07:39 AM.

  7. #7
    Registered User
    Join Date
    Jul 2008
    Posts
    14
    Thnak you Clairvoyant1332!

    I wasn't making a difference between pure virtual functions and virtual function, thought they are the same.
    So :
    Code:
    virtual ~Base() //=0
    {
          delete[] str;       // str = new char[size]; in constructor.     
    };
    is correct.
    Last edited by tzakieta; 09-11-2008 at 07:39 AM.

  8. #8
    The larch
    Join Date
    May 2006
    Posts
    3,573
    If you want to keep the destructor pure for some reason, this is how it would work:

    Code:
    class Base
    {
        virtual ~Base() = 0;
        ...
    };
    
    Base::~Base()
    {
        ....
    }
    Similarly for any other pure method that you still want to provide an implementation for.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  9. #9
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,895
    Quote Originally Posted by Clairvoyant1332 View Post
    The difference is a pure virtual function does not have an implementation and therefore must be implemented in a derived class.
    Not correct. A pure virtual function doesn't need to have an implementation, and it must be overridden in a derived class. You can write an implementation for a pure virtual function. However, to call it you must make the call explicitly qualified. Typically, this might be used to provide some default action.
    Code:
    void Derived::somevirt()
    {
      // Do something.
      Base::somevirt();
      // Do more.
    }
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  10. #10
    The superhaterodyne twomers's Avatar
    Join Date
    Dec 2005
    Location
    Ireland
    Posts
    2,273
    Just something I noticed...
    Code:
          Base() : bsnr(0)          // default constructor
          {
           bstxt = new char[size];   // allocation for a string of 'size' 
           strcpy(bstxt,  "smth");     // initialisation
           }
    What's the story with size here? It should probably be passed into another constructor, but one which is parameterised... as follows:
    Code:
    Base( const unsigned int &size ) : bsnr(0)
    {
      // as before
    }

  11. #11
    Registered User
    Join Date
    Jul 2008
    Posts
    14
    size dosen't matter there, I sould have put 23 or 399 there. it was more like an symbol not a var.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Virtual Box
    By ssharish2005 in forum Tech Board
    Replies: 3
    Last Post: 02-12-2009, 05:08 AM
  2. Replies: 48
    Last Post: 09-26-2008, 03:45 AM
  3. Program with Shapes using Virtual Functions
    By goron350 in forum C++ Programming
    Replies: 12
    Last Post: 07-17-2005, 01:42 PM
  4. C++ XML Class
    By edwardtisdale in forum C++ Programming
    Replies: 0
    Last Post: 12-10-2001, 11:14 PM
  5. Exporting Object Hierarchies from a DLL
    By andy668 in forum C++ Programming
    Replies: 0
    Last Post: 10-20-2001, 01:26 PM