From: internetpet on
Say you have these files:

BigClazz.h

class Clazz; // Note the forward declaration only , no include
"Clazz.h"
class BigClazz
{
public:
BigClazz();
~BigClazz();
Clazz* pclazz;
};

BigClazz.cpp

#include "BigClazz.h"
BigClazz::BigClazz(){}
BigClazz::~BigClazz()
{
delete pclazz; // Here the destructor of of the Clazz object
will not be called
}

Clazz.h

class Clazz
{
public:
Clazz();
~Clazz();
};


Clazz.cpp

#include "Clazz.h"
Clazz::Clazz(){};
Clazz::~Clazz(){};


main.cpp

int main(int argc, char *argv[])
{
BigClazz* pVM = new BigClazz();
pVM->pclazz = new Clazz();
delete pVM;
}

If you run this you'll see that the Clazz destructor will not be
called when BigClazz does "delete pclazz;" in it's own destructor. But
if you replace the forward declaration in BigClazz (class Clazz;) with
an include
(#include "Clazz.h") then it works.

Any idea why?

Thanks
Eric


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Daniel Krügler on
On 22 Apr., 04:43, internetpet <internet...(a)hotmail.com> wrote:
> BigClazz.h
>
> class Clazz; // Note the forward declaration only , no include
> "Clazz.h"
> class BigClazz
> {
> public:
> BigClazz();
> ~BigClazz();
> Clazz* pclazz;
> };
>
> BigClazz.cpp
>
> #include "BigClazz.h"
> BigClazz::BigClazz(){}
> BigClazz::~BigClazz()
> {
> delete pclazz; // Here the destructor of of the Clazz object
> will not be called
> }

You are violating the constraints of Our Holy Standard here:

[expr.delete]/5: "If the object being deleted has incomplete class type
at the point of deletion and the complete class has a non-trivial destructor
or a deallocation function, the behavior is undefined."

> #include "Clazz.h"
> Clazz::Clazz(){};
> Clazz::~Clazz(){};

This is a user-defined d'tor, therefore it is non-trivial according to the
standard, [class.dtor]/3+4:

"If a class has no user-declared destructor, a destructor is declared implicitly.
An implicitly-declared destructor is an inline public member of its class. A
destructor is trivial if it is an implicitly-declared destructor and [..]
Otherwise, the destructor is non-trivial."

HTH & Greetings from Bremen,

Daniel Kr�gler


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Triple-DES on
On 22 Apr, 04:43, internetpet <internet...(a)hotmail.com> wrote:
> Say you have these files:
>
> BigClazz.h
>
> class Clazz; // Note the forward declaration only , no include
> "Clazz.h"
> class BigClazz
> {
> public:
> BigClazz();
> ~BigClazz();
> Clazz* pclazz;
> };
>
> BigClazz.cpp
>
> #include "BigClazz.h"
> BigClazz::BigClazz(){}
> BigClazz::~BigClazz()
> {
> delete pclazz; // Here the destructor of of the Clazz object
> will not be called
> }
>
> Clazz.h
>
> class Clazz
> {
> public:
> Clazz();
> ~Clazz();
> };
>
> Clazz.cpp
>
> #include "Clazz.h"
> Clazz::Clazz(){};
> Clazz::~Clazz(){};
>
> main.cpp
>
> int main(int argc, char *argv[])
> {
> BigClazz* pVM = new BigClazz();
> pVM->pclazz = new Clazz();
> delete pVM;
> }
>
> If you run this you'll see that the Clazz destructor will not be
> called when BigClazz does "delete pclazz;" in it's own destructor. But
> if you replace the forward declaration in BigClazz (class Clazz;) with
> an include
> (#include "Clazz.h") then it works.
>
> Any idea why?

Yes. According to [expr.delete]/5 in the standard (with my comments in
parens):

If the object being deleted has incomplete class type (in this case,
forward declared) at the point of deletion and the complete class has
a non-trivial destructor (you declared your own dtor, so it's non-
trivial) or a deallocation function, the behavior is undefined (which
usually means not calling the destructor in this case).

To fix this, simply #include "Clazz.h" in BigClazz.cpp, so that the
type is complete at the point of deletion.

--
DP

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Travis Vitek on
On Apr 21, 7:43 pm, internetpet <internet...(a)hotmail.com> wrote:
> Say you have these files:
>
> BigClazz.h
>
> class Clazz; // Note the forward declaration only , no include
> "Clazz.h"
> class BigClazz
> {
> public:
> BigClazz();
> ~BigClazz();
> Clazz* pclazz;
> };
>
> BigClazz.cpp
>
> #include "BigClazz.h"
> BigClazz::BigClazz(){}
> BigClazz::~BigClazz()
> {
> delete pclazz; // Here the destructor of of the Clazz object
> will not be called
> }
>

<snip>

>
> If you run this you'll see that the Clazz destructor will not be
> called when BigClazz does "delete pclazz;" in it's own destructor. But
> if you replace the forward declaration in BigClazz (class Clazz;) with
> an include
> (#include "Clazz.h") then it works.
>
> Any idea why?

Because the C++ standard allows pointers to incomplete class types to
be deleted but if the class has a non-trivial destructor or a class
operator delete the behavior is undefined.

You can easily work around the problem by including Clazz.h into
Bigclazz.cpp so that the type you are deleting is complete at the
point you delete it.

Travis


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: marlow.andrew on
On 22 Apr, 03:43, internetpet <internet...(a)hotmail.com> wrote:
> Say you have these files:
>
> BigClazz.h
>
> class Clazz; // Note the forward declaration only , no include
> "Clazz.h"
> class BigClazz
> {
> public:
> BigClazz();
> ~BigClazz();
> Clazz* pclazz;
> };
>
> BigClazz.cpp
>
> #include "BigClazz.h"
> BigClazz::BigClazz(){}
> BigClazz::~BigClazz()
> {
> delete pclazz; // Here the destructor of of the Clazz object
> will not be called
> }

[snip]

> If you run this you'll see that the Clazz destructor will not be
> called when BigClazz does "delete pclazz;" in it's own destructor. But
> if you replace the forward declaration in BigClazz (class Clazz;) with
> an include
> (#include "Clazz.h") then it works.
>
> Any idea why?

The type must be known for delete blah to be compilable.
Hence your code will not compile. Here's the error I got from gcc:

BigClazz.cpp: In destructor �BigClazz::~BigClazz()�:
BigClazz.cpp:5: warning: possible problem detected in invocation of
delete operator:
BigClazz.cpp:5: warning: invalid use of undefined type �struct Clazz�
BigClazz.h:1: warning: forward declaration of �struct Clazz�
BigClazz.cpp:5: note: neither the destructor nor the class-specific
operator delete will be called, even if they are declared when the
class is defined.

Says it all, I think.
You wouldn't be using a Micro$oft compiler by any chance?

-Andrew Marlow


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]