Inheritance and destructors, guidance please

Discussion in 'C++' started by Warwick, Oct 8, 2003.

  1. Warwick

    Warwick Guest

    Hi

    I could use some help with inheritance and destructors.
    I have been following an example in a book and the example has lead to
    a situation which I have
    reduced to a contrived example that follows.


    B is derived from A, and C is derived from B.
    All the derivations are public.
    B has nothing to do on destruction. C and A do.

    It seems to work, even tho B did not override the destructor declared
    virtual in A. However I dont know if its leaking memory or not since I
    dont really know how to test for that.


    I have 3 related questions.



    class A
    {

    char* MemSpace;
    protected:
    virtual int fooA ();

    public:
    A () { MemSpace = new char[256];}
    virtual ~A (); //can't define here right?
    };

    A::~A() //A's destructor
    {
    delete MemSpace;
    }


    class B : public A
    {

    public:
    B () : A::A() {}
    };

    class c : public B
    {
    char* MoreSpace;
    protected:
    virtual int fooA ();
    public:
    C () :B::B() { MoreSpace = new char[256];}
    virtual ~C ();

    };

    Q. If B has not defined a destructor what happens if
    {
    B* tmp = new B();
    //and later
    delete tmp;
    }

    Will A's destructor be called automatically?



    Q Writing C's destructor.
    Should I write

    ~C ()
    {
    delete MoreSpace;
    A:~A();
    }

    or

    ~C ()
    {
    delete MoreSpace;
    delete this;
    }
    or

    ~C ()
    {
    delete MoreSpace;
    delete dyanmic_cast<A*>(this);
    }
    or
    something else?

    Q Overriding fooA.

    is
    int C:fooA ()
    {
    //do stuff
    A:fooA (); // call A's fooA.
    }

    the same as
    int C:fooA ()
    {
    //do stuff
    B:fooA (); // call B's surfaced fooA which calls A's fooA.
    }

    ?

    Any guidance, help is very much appreciated.

    Best
    Warwick
    Warwick, Oct 8, 2003
    #1
    1. Advertising

  2. Warwick

    Attila Feher Guest

    Warwick wrote:
    [SNIP]
    > class A
    > {
    >
    > char* MemSpace;
    > protected:
    > virtual int fooA ();
    >
    > public:
    > A () { MemSpace = new char[256];}
    > virtual ~A (); //can't define here right?
    > };


    You can. It will either make sense or not. The rule of thumb: don't define
    it there is it can change (destructors can) or if it is unlikely to be
    called on a non-pointer/reference... that one is quite specific for each
    case. BTW it is not only "there" but any kind of inline definition.

    > class B : public A
    > {
    >
    > public:
    > B () : A::A() {}


    You don't need to write that A::A(), it is the default.

    > };
    >
    > class c : public B
    > {
    > char* MoreSpace;
    > protected:
    > virtual int fooA ();
    > public:
    > C () :B::B() { MoreSpace = new char[256];}
    > virtual ~C ();
    >
    > };
    >
    > Q. If B has not defined a destructor what happens if
    > {
    > B* tmp = new B();
    > //and later
    > delete tmp;
    > }
    >
    > Will A's destructor be called automatically?


    Yes. And the compiler generated B destructor will override the one in A,
    but it will also call the one in A.

    > Q Writing C's destructor.
    > Should I write
    >
    > ~C ()
    > {
    > delete MoreSpace;
    > A:~A();
    > }


    Nope. The destructor of A will be called automagically. You do not need to
    do anything.

    > or
    >
    > ~C ()
    > {
    > delete MoreSpace;
    > delete this;


    No way. Don't ever write delete this in a destructor.

    > }
    > or
    >
    > ~C ()
    > {
    > delete MoreSpace;
    > delete dyanmic_cast<A*>(this);
    > }
    > or
    > something else?


    Nope.

    > Q Overriding fooA.
    >
    > is
    > int C:fooA ()
    > {
    > //do stuff
    > A:fooA (); // call A's fooA.
    > }
    >
    > the same as
    > int C:fooA ()
    > {
    > //do stuff
    > B:fooA (); // call B's surfaced fooA which calls A's fooA.
    > }
    >
    > ?


    They are equvivalent. It is better to use B::fooA, since then C will not
    need to know about B inheriting from A.

    --
    Attila aka WW
    Attila Feher, Oct 8, 2003
    #2
    1. Advertising

  3. > I could use some help with inheritance and destructors.
    > I have been following an example in a book and the example has lead to
    > a situation which I have
    > reduced to a contrived example that follows.
    >
    >
    > B is derived from A, and C is derived from B.
    > All the derivations are public.
    > B has nothing to do on destruction. C and A do.
    >
    > It seems to work, even tho B did not override the destructor declared
    > virtual in A. However I dont know if its leaking memory or not since I
    > dont really know how to test for that.
    >
    > I have 3 related questions.
    >
    > class A
    > {
    >
    > char* MemSpace;
    > protected:
    > virtual int fooA ();
    >
    > public:
    > A () { MemSpace = new char[256];}
    > virtual ~A (); file://can't define here right?
    > };
    >
    > A::~A() file://A's destructor
    > {
    > delete MemSpace;
    > }
    >
    >
    > class B : public A
    > {
    >
    > public:
    > B () : A::A() {}
    > };
    >
    > class c : public B
    > {
    > char* MoreSpace;
    > protected:
    > virtual int fooA ();
    > public:
    > C () :B::B() { MoreSpace = new char[256];}
    > virtual ~C ();
    >
    > };
    >
    > Q. If B has not defined a destructor what happens if
    >


    > B* tmp = new B();
    > file://and later
    > delete tmp;
    > }
    >
    > Will A's destructor be called automatically?


    Yes, base class destructors will always be called, even if a derived
    class does not implement its own destructor.

    > Q Writing C's destructor.
    > Should I write
    >
    > ~C ()
    >


    > delete MoreSpace;
    > A:~A();
    > }


    No, once C::~C() has finished A::~A() will automatically be invoked.

    > ~C ()
    > {
    > delete MoreSpace;
    > delete this;
    > }


    NO!!!!!!!! Don't do 'delete this' in the destructor!!!! This is never
    correct, anything might happen if you do this though it would probably
    lead to infinite recursion as 'delete this' will call the destructor of
    class C...etc. After the destructor of a class instance has completed,
    the memory that that instance occupies will be released.

    > or
    >
    > ~C ()
    > {
    > delete MoreSpace;
    > delete dyanmic_cast<A*>(this);
    > }


    No, don't delete the base class, has the same effect as the previous
    attempt.

    > or
    > something else?


    C:: ~C ()
    {
    delete MoreSpace;
    }

    will do.

    > Q Overriding fooA.
    > is
    > int C:fooA ()
    > {
    > file://do stuff
    > A:fooA (); // call A's fooA.
    > }
    >
    > the same as
    > int C:fooA ()
    > {
    > file://do stuff
    > B:fooA (); // call B's surfaced fooA which calls A's fooA.
    > }


    It has the same effect because class B doesn't override fooA().

    > Any guidance, help is very much appreciated.


    Maybe you need a better book, a good book should explain these things.
    See www.accu.org for book recommendations.

    --
    Peter van Merkerk
    peter.van.merkerk(at)dse.nl
    Peter van Merkerk, Oct 8, 2003
    #3
  4. Warwick

    Warwick Guest

    On Wed, 8 Oct 2003 11:08:45 +0200, "Peter van Merkerk"
    <> wrote:

    >> I could use some help with inheritance and destructors.
    >> I have been following an example in a book and the example has lead to
    >> a situation which I have
    >> reduced to a contrived example that follows.
    >>
    >>
    >> B is derived from A, and C is derived from B.
    >> All the derivations are public.
    >> B has nothing to do on destruction. C and A do.
    >>
    >> It seems to work, even tho B did not override the destructor declared
    >> virtual in A. However I dont know if its leaking memory or not since I
    >> dont really know how to test for that.
    >>
    >> I have 3 related questions.
    >>
    >> class A
    >> {
    >>
    >> char* MemSpace;
    >> protected:
    >> virtual int fooA ();
    >>
    >> public:
    >> A () { MemSpace = new char[256];}
    >> virtual ~A (); file://can't define here right?
    >> };
    >>
    >> A::~A() file://A's destructor
    >> {
    >> delete MemSpace;
    >> }
    >>
    >>
    >> class B : public A
    >> {
    >>
    >> public:
    >> B () : A::A() {}
    >> };
    >>
    >> class c : public B
    >> {
    >> char* MoreSpace;
    >> protected:
    >> virtual int fooA ();
    >> public:
    >> C () :B::B() { MoreSpace = new char[256];}
    >> virtual ~C ();
    >>
    >> };
    >>
    >> Q. If B has not defined a destructor what happens if
    >>

    >
    >> B* tmp = new B();
    >> file://and later
    >> delete tmp;
    >> }
    >>
    >> Will A's destructor be called automatically?

    >
    >Yes, base class destructors will always be called, even if a derived
    >class does not implement its own destructor.
    >
    >> Q Writing C's destructor.
    >> Should I write
    >>
    >> ~C ()
    >>

    >
    >> delete MoreSpace;
    >> A:~A();
    >> }

    >
    >No, once C::~C() has finished A::~A() will automatically be invoked.
    >
    >> ~C ()
    >> {
    >> delete MoreSpace;
    >> delete this;
    >> }

    >
    >NO!!!!!!!! Don't do 'delete this' in the destructor!!!! This is never
    >correct, anything might happen if you do this though it would probably
    >lead to infinite recursion as 'delete this' will call the destructor of
    >class C...etc. After the destructor of a class instance has completed,
    >the memory that that instance occupies will be released.
    >
    >> or
    >>
    >> ~C ()
    >> {
    >> delete MoreSpace;
    >> delete dyanmic_cast<A*>(this);
    >> }

    >
    >No, don't delete the base class, has the same effect as the previous
    >attempt.
    >
    >> or
    >> something else?

    >
    >C:: ~C ()
    >{
    > delete MoreSpace;
    >}
    >
    >will do.
    >
    >> Q Overriding fooA.
    >> is
    >> int C:fooA ()
    >> {
    >> file://do stuff
    >> A:fooA (); // call A's fooA.
    >> }
    >>
    >> the same as
    >> int C:fooA ()
    >> {
    >> file://do stuff
    >> B:fooA (); // call B's surfaced fooA which calls A's fooA.
    >> }

    >
    >It has the same effect because class B doesn't override fooA().
    >
    >> Any guidance, help is very much appreciated.

    >
    >Maybe you need a better book, a good book should explain these things.
    >See www.accu.org for book recommendations.


    Thanks very much to you both, Precisely the answers I required.

    cheers :)
    Warwick, Oct 8, 2003
    #4
  5. <snip>

    > Thanks very much to you both, Precisely the answers I required.


    Please, do not quote the whole post for thanks.


    Jonathan
    Jonathan Mcdougall, Oct 9, 2003
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jimmy
    Replies:
    0
    Views:
    419
    Jimmy
    Oct 15, 2004
  2. Christopher Benson-Manica

    Multiple inheritance and destructors

    Christopher Benson-Manica, Feb 26, 2004, in forum: C++
    Replies:
    3
    Views:
    343
    John Harrison
    Feb 26, 2004
  3. ash

    C++ guidance please!

    ash, Jul 17, 2004, in forum: C++
    Replies:
    2
    Views:
    373
    Sharad Kala
    Jul 17, 2004
  4. Dfenestr8
    Replies:
    2
    Views:
    369
    Sandy Norton
    Jul 4, 2003
  5. Guest
    Replies:
    8
    Views:
    338
    Steven Cheng[MSFT]
    Dec 29, 2006
Loading...

Share This Page