Thread: Destructors error

  1. #1
    Registered User
    Join Date
    Mar 2005
    Posts
    54

    Destructors error

    Hi, I'm having trouble with the destructors of a derived class from a base class, here are the codes

    Base Class of Asteroid.h
    Code:
    #ifndef ASTEROID_H
    #define ASTEROID_H
    #include <QPainter>
    
    using std::string;
    
    class Asteroid
    {
      public:
        Asteroid *aNext;
        virtual float x_data(void) const = 0;
        virtual float y_data(void) const = 0;
        virtual string strType_data(void) const = 0;
        virtual int radius_data(void) const = 0;
        virtual int vertice_A(void) const = 0;
        virtual int vertice_B(void) const = 0;
        virtual ~Asteroid() = 0;
    };
    
    #endif
    Derived Class AsteroidNode.h
    Code:
    #ifndef ASTEROIDTYPE1_H
    #define ASTEROIDTYPE1_H
    
    #include <iostream>
    #include <QPainter>
    #include <cstdlib>
    
    #include "Asteroid.h"
    
    using std::string;
    
    class AsteroidType1 : public Asteroid
    {
      public:
        AsteroidType1(string);
        AsteroidType1(string,float,float);
        ~AsteroidType1();
    
        float x_data(void) const;
        float y_data(void) const;
        string strType_data(void) const;
        int vertice_A(void) const;
        int vertice_B(void) const;
        int radius_data(void) const;
    
      private:
        float x;
        float y;
        string aType;
    };
    
    #endif
    AsteroidNode.cpp
    Code:
    #include "AsteroidType1.h"
    
    // Default Constructor
    AsteroidType1::AsteroidType1(string strType)
      {
        aType = strType;
        x = 9;
        aNext = NULL;
      }
    
    // Alternative constructor
    AsteroidType1::AsteroidType1(string strType, float x_data, float y_data)
      {
        aType = strType;
        x = x_data;
        y = y_data;
        aNext = NULL;
      }
    
    AsteroidType1::~AsteroidType1()
      {
      }
    
    // Get X value
    float AsteroidType1::x_data(void) const
      {
        return x;
      }
    
    // Get Y value
    float AsteroidType1::y_data(void) const
      {
        return y;
      }
    
    string AsteroidType1::strType_data(void) const
      {
        return aType;
      }
    
    int AsteroidType1::radius_data(void) const
      {
        return 1;
      }
    
    int AsteroidType1::vertice_A(void) const
      {
        return 1;
      }
    
    int AsteroidType1::vertice_B(void) const
      {
        return 1;
      }
    Error I had :

    Code:
    AsteroidNode.o: In function `AsteroidNode::AsteroidNode(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, float, float, int, int, int)':
    AsteroidNode.cpp:(.text+0x167): undefined reference to `Asteroid::~Asteroid()'
    AsteroidNode.o: In function `AsteroidNode::AsteroidNode()':
    AsteroidNode.cpp:(.text+0x211): undefined reference to `Asteroid::~Asteroid()'
    AsteroidNode.o: In function `AsteroidNode::AsteroidNode(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, float, float, int, int, int)':
    AsteroidNode.cpp:(.text+0x2c7): undefined reference to `Asteroid::~Asteroid()'
    AsteroidNode.o: In function `AsteroidNode::AsteroidNode()':
    AsteroidNode.cpp:(.text+0x371): undefined reference to `Asteroid::~Asteroid()'
    AsteroidNode.o: In function `AsteroidNode::~AsteroidNode()':
    AsteroidNode.cpp:(.text+0x3d7): undefined reference to `Asteroid::~Asteroid()'
    AsteroidNode.o:AsteroidNode.cpp:(.text+0x41b): more undefined references to `Asteroid::~Asteroid()' follow
    collect2: ld returned 1 exit status
    make: *** [game] Error 1
    Any ideas? I've yet to add anything inside the destructor function because I haven't finish my work yet.

  2. #2
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Code:
    virtual ~Asteroid() = 0;
    Virtual destructors are a good idea. Pure virtual destructors, on the other hand, are not.

    Here's why. With a virtual destructor, code like this will work properly.
    Code:
    class base {};
    class derived : public base {};
    
    base *b = new derived;
    delete b;
    But a pure virtual destructor means that the derived class will implement the base class's destructor. Which is impossible.
    Last edited by dwks; 10-13-2007 at 08:01 PM.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  3. #3
    Registered User
    Join Date
    Mar 2005
    Posts
    54
    *EDIT
    So its like

    Code:
    class base
    {
      public:
        virtual ~base();
    };
    
    class derived : public base
    {
      public:
        derived();
    };
    
    int main()
    {
      base *b = new derived();
     
      delete b;
    }
    But it throws me more errors of the same kind. Worst even more.
    Last edited by DarrenY; 10-13-2007 at 08:10 PM.

  4. #4
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    [edit] With that code of yours, you need to implement ~derived(), I should imagine. [/edit]

    You want to use virtual destructors so that the derived classes' destructors will be called properly from a pointer to a base class.
    Code:
    #include <iostream>
    
    class virtualbase {
    public:
        virtual ~virtualbase() { std::cout << "~virtualbase()\n"; }
    };
    
    class virtualderived : public virtualbase {
    public:
        virtual ~virtualderived() { std::cout << "~virtualderived()\n"; }
    };
    
    class nonvirtualbase {
    public:
        ~nonvirtualbase() { std::cout << "~virtualbase()\n"; }
    };
    
    class nonvirtualderived : public nonvirtualbase {
    public:
        ~nonvirtualderived() { std::cout << "~virtualderived()\n"; }
    };
    
    int main() {
        std::cout << "==== Classes with virtual destructors:\n";
    
        virtualbase *vb = new virtualbase;
        virtualbase *vd = new virtualderived;
        std::cout << "---- Deleting a virtualbase\n";
        delete vb;
        std::cout << "---- Deleting a virtualderived\n";
        delete vd;
        
        std::cout << "\n==== Classes without virtual destructors:\n";
        
        nonvirtualbase *nvb = new nonvirtualbase;
        nonvirtualbase *nvd = new nonvirtualderived;
        std::cout << "---- Deleting a nonvirtualbase\n";
        delete nvb;
        std::cout << "---- Deleting a nonvirtualderived\n";
        delete nvd;
    }
    Output:
    Code:
    ==== Classes with virtual destructors:
    ---- Deleting a virtualbase
    ~virtualbase()
    ---- Deleting a virtualderived
    ~virtualderived()
    ~virtualbase()
    
    ==== Classes without virtual destructors:
    ---- Deleting a nonvirtualbase
    ~virtualbase()
    ---- Deleting a nonvirtualderived
    ~virtualbase()
    I'm not sure what use pure virtual destructors might be, as a C programmer myself . . . maybe someone else can help.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  5. #5
    Registered User
    Join Date
    Mar 2005
    Posts
    54
    Thanks alot. I kind of manage to implement it in my work.

  6. #6
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    You can declare a pure virtual destructor, but you still have to implement that classes destructor body, so there isn't any point really.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Pure virtual destructors, on the other hand, are not.
    I disagree with such an absolute statement. For example, there might be a case where a class should be an abstract base class, but it has no good candidates for a pure virtual function. In such a case, having a pure virtual function could be a good idea, though as iMalc pointed out, the base class destructor still needs to be defined.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by dwks View Post
    But a pure virtual destructor means that the derived class will implement the base class's destructor. Which is impossible.
    Rubbish.

    A pure virtual destructor makes the class abstract (unable to be instantiated) even if the class has no other pure virtual functions. There is no requirement for a derived class to implement a base class's pure virtual destructor. However, the base class must define (i.e. implement) a pure virtual destructor because the destructor of a derived class will implicitly invoke (i.e. call) the base class destructor.

    The only functional difference between a pure virtual destructor and any other pure virtual function is that the base class must define a pure virtual destructor, while definition of any other pure virtual function by the base class is strictly optional. Either way, the base class cannot be instantiated.

    This means it is possible to do this;
    Code:
    class Base
    {
        public:
    
               virtual ~Base() = 0;
               virtual void Func() = 0;
    };
    
    Base::Base()    // this implementation is mandatory
    {
    }
    
    void Base::Func()   // this implementation is optional
    {
    }
    
    class Derived : public Base
    {
        public:
    
             ~Derived();
            void Func();
    };
    
    Derived::Derived()   // implicitly invokes Base::Base()
    {
    }
    
    void Derived::Func()
    {
        Base::Func();   // yes we can call Base::Func() as we have implemented it
    }
    
    int main()
    {
         // Base x;   // invalid as Base cannot be instantiated.
         Derived y;   // OK
    
         y.Func();   // calls Derived::Func() which, in turn, calls Base::Func()
    
          // y destructed here.  Derived::~Derived() is invoked, then Base::~Base()
    }
    The reason for DarrenY's problem is that he has not defined (i.e. implemented) a destructor for AsteroidNode(). Making that destructor pure virtual does not allow him to get away without defining it.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Getting an error with OpenGL: collect2: ld returned 1 exit status
    By Lorgon Jortle in forum C++ Programming
    Replies: 6
    Last Post: 05-08-2009, 08:18 PM
  2. An error is driving me nuts!
    By ulillillia in forum C Programming
    Replies: 5
    Last Post: 04-04-2009, 09:15 PM
  3. Making C DLL using MSVC++ 2005
    By chico1st in forum C Programming
    Replies: 26
    Last Post: 05-28-2008, 01:17 PM
  4. Connecting to a mysql server and querying problem
    By Diod in forum C++ Programming
    Replies: 8
    Last Post: 02-13-2006, 10:33 AM
  5. Couple C questions :)
    By Divx in forum C Programming
    Replies: 5
    Last Post: 01-28-2003, 01:10 AM