 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Gustavo Guerra Guest
|
Posted: Wed Sep 29, 2004 5:47 pm Post subject: Question about virtual destructors |
|
|
Hello
I need a little help here
Will the following work correctly?
class XPTO
{
public:
int i;
xpto_ptr<int*> iptr;
};
class XPTI: public XPTO
{
public:
double d;
xpto_ptr<double*> dptr;
};
int main()
{
XPTO* ptr = new XPTI();
delete ptr;
}
being xpto_ptr something like scoped_ptr, auto_ptr, move_ptr and variations
Or will I have to redefine XPTO as
class XPTO
{
public:
int i;
virtual ~XPTO() {}
};
to have correct behavior?
I'm in doubt because I don't directly allocate heap data in any class of the
hierarchy.
Regards
Gustavo Guerra
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ulrich Eckhardt Guest
|
Posted: Fri Oct 01, 2004 11:39 am Post subject: Re: Question about virtual destructors |
|
|
Gustavo Guerra wrote:
| Quote: | Will the following work correctly?
class XPTO
{
public:
int i;
xpto_ptr<int*> iptr;
};
class XPTI: public XPTO
{
public:
double d;
xpto_ptr<double*> dptr;
};
int main()
{
XPTO* ptr = new XPTI();
|
Allocate an XPTI and store it in a pointer to the baseclass. OK.
This uses ptr's type(XPTO) to determine which dtor to call. XPTO's dtor is
not virtual though, which is why only XPTO's dtor gets called. This is not
OK.
If it had been virtual, the call would have been delegated to the dtor of
the most derived class, which would have been right.
| Quote: | being xpto_ptr something like scoped_ptr, auto_ptr, move_ptr and
variations
|
The above won't work, regardless of the smart pointer you use.
| Quote: | Or will I have to redefine XPTO as
class XPTO
{
public:
int i;
virtual ~XPTO() {}
};
to have correct behavior?
|
Yes. If you want to polymorphically delete an object, you need a virtual
dtor.
Speaking of smart pointers, this will work correctly:
boost::shared_ptr<XPTO> ptr = boost::shared_ptr<XPTI>(new XPTI);
When ptr goes out of scope, it will correctly call XPTI's dtor. Event if the
object finally ends in a shared_ptr<void> it will work correctly, if the
first owner was correct.
This is specific to boost::shared_ptr<>, std::auto_ptr<> won't do it, I
don't know about the move_ptr<> you quoted.
Another thing to consider is making the base classes dtor protected. That
way, you can't call the wrong dtor and your program will fail at compile
time.
Uli
--
FAQ: http://parashift.com/c++-faq-lite/
/* bittersweet C++ */
default: break;
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Victor Bazarov Guest
|
Posted: Fri Oct 01, 2004 11:44 am Post subject: Re: Question about virtual destructors |
|
|
"Gustavo Guerra" <gmcg (AT) acm (DOT) org> wrote...
| Quote: | Hello
I need a little help here
Will the following work correctly?
class XPTO
{
public:
int i;
xpto_ptr<int*> iptr;
};
class XPTI: public XPTO
{
public:
double d;
xpto_ptr<double*> dptr;
};
int main()
{
XPTO* ptr = new XPTI();
delete ptr;
}
being xpto_ptr something like scoped_ptr, auto_ptr, move_ptr and
variations
Or will I have to redefine XPTO as
class XPTO
{
public:
int i;
virtual ~XPTO() {}
};
to have correct behavior?
|
The latter. Any time you delete an object of a derived class through
a pointer to a base class, the destructor has to be virtual or the
behaviour is undefined.
| Quote: |
I'm in doubt because I don't directly allocate heap data in any class of
the
hierarchy.
|
It does not matter.
V
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Zian Smith Guest
|
Posted: Fri Oct 01, 2004 11:48 am Post subject: Re: Question about virtual destructors |
|
|
"Gustavo Guerra" <gmcg (AT) acm (DOT) org> wrote
| Quote: | Hello
I need a little help here
Will the following work correctly?
class XPTO
{
public:
int i;
xpto_ptr<int*> iptr;
};
class XPTI: public XPTO
{
public:
double d;
xpto_ptr<double*> dptr;
};
int main()
{
XPTO* ptr = new XPTI();
delete ptr;
}
|
well since you essentially have a base class pointer that points to a
derived class object, you should have a virtual destructor in your
base class so that the derived class destructor is called when you
delete ptr. The destructors are probably where you want to delete iptr
and dptr.
| Quote: |
being xpto_ptr something like scoped_ptr, auto_ptr, move_ptr and variations
Or will I have to redefine XPTO as
class XPTO
{
public:
int i;
virtual ~XPTO() {}
};
to have correct behavior?
I'm in doubt because I don't directly allocate heap data in any class of the
hierarchy.
|
From what I can understand from your code, iptr and dptr will probably
point to data on the heap when you allocate memory for them somewhere
in your code, and you should delete them in the class destructors..
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Bob Hairgrove Guest
|
Posted: Fri Oct 01, 2004 11:54 am Post subject: Re: Question about virtual destructors |
|
|
On 29 Sep 2004 13:47:23 -0400, "Gustavo Guerra" <gmcg (AT) acm (DOT) org> wrote:
[snip...]
| Quote: | Or will I have to redefine XPTO as
class XPTO
{
public:
int i;
virtual ~XPTO() {}
};
to have correct behavior?
[snip] |
Yes.
--
Bob Hairgrove
[email]NoSpamPlease (AT) Home (DOT) com[/email]
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
news Guest
|
Posted: Fri Oct 01, 2004 11:57 am Post subject: Re: Question about virtual destructors |
|
|
"Gustavo Guerra" <gmcg (AT) acm (DOT) org> wrote
| Quote: | XPTO* ptr = new XPTI();
delete ptr;
|
No. You are deleting via a pointer to a base class. XPTO must have virtual destructor.
| Quote: | I'm in doubt because I don't directly allocate heap data in any class of the
hierarchy.
|
What does the above have to do with it? It doesn't have anything to do with the
heap data the class allocates. It has to do with your call to new and delete. You
need the virtual destructor even if XPTO and XPTI didn't have any data members.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Alberto Barbati Guest
|
Posted: Fri Oct 01, 2004 4:57 pm Post subject: Re: Question about virtual destructors |
|
|
Gustavo Guerra wrote:
| Quote: | Hello
I need a little help here
Will the following work correctly?
[code omitted]
|
No.
| Quote: | Or will I have to redefine XPTO as
class XPTO
{
public:
int i;
virtual ~XPTO() {}
};
to have correct behavior?
|
Yes. (but what happened to the xpto_ptr<int*> member?)
Alberto
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Gustavo Guerra Guest
|
Posted: Fri Oct 01, 2004 5:56 pm Post subject: Re: Question about virtual destructors |
|
|
"news" <news (AT) news (DOT) newshosting.com> wrote
| Quote: |
"Gustavo Guerra" <gmcg (AT) acm (DOT) org> wrote in message
news:2ruag9F1f15q0U1 (AT) uni-berlin (DOT) de...
XPTO* ptr = new XPTI();
delete ptr;
No. You are deleting via a pointer to a base class. XPTO must have
virtual destructor.
I'm in doubt because I don't directly allocate heap data in any class of
the
hierarchy.
What does the above have to do with it? It doesn't have anything to do
with the
heap data the class allocates. It has to do with your call to new and
delete. You
need the virtual destructor even if XPTO and XPTI didn't have any data
members.
|
My question is solely based on the fact that I don't need any destructor at
all, so there's no issue of calling the wrong destructor. I'm uncertain is
if the delete operation frees the correct amount of memory. For example,
free in C, on wich delete is bases, doesn't need to know the type, it can
even be a void *, as the standard heap allocator as information regarding
the ammount of memory it allocated starting at that address.
Regards
Gustavo Guerra
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Zian Smith Guest
|
Posted: Sat Oct 02, 2004 2:20 pm Post subject: Re: Question about virtual destructors |
|
|
"Gustavo Guerra" <gmcg (AT) acm (DOT) org> wrote
| Quote: | Hello
I need a little help here
Will the following work correctly?
class XPTO
{
public:
int i;
xpto_ptr<int*> iptr;
};
class XPTI: public XPTO
{
public:
double d;
xpto_ptr<double*> dptr;
};
int main()
{
XPTO* ptr = new XPTI();
delete ptr;
}
|
well since you essentially have a base class pointer that points to a
derived class object, you should have a virtual destructor in your
base class so that the derived class destructor is called when you
delete ptr. The destructors are probably where you want to delete iptr
and dptr.
| Quote: |
being xpto_ptr something like scoped_ptr, auto_ptr, move_ptr and variations
Or will I have to redefine XPTO as
class XPTO
{
public:
int i;
virtual ~XPTO() {}
};
to have correct behavior?
I'm in doubt because I don't directly allocate heap data in any class of the
hierarchy.
|
From what I can understand from your code, iptr and dptr will probably
point to data on the heap when you allocate memory for them somewhere
in your code, and you should delete them in the class destructors..
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Frank Birbacher Guest
|
Posted: Sun Oct 03, 2004 3:28 am Post subject: Re: Question about virtual destructors |
|
|
Hi!
Gustavo Guerra wrote:
| Quote: | My question is solely based on the fact that I don't need any destructor at
all, so there's no issue of calling the wrong destructor.
|
Just because you didn't explicitly write a dtor, doesn't mean
there won't be any. The compiler automatically generates a
default destructor which will invoke the dtors of all members.
Since now in your example the dtor of the most derived class
(XPTI) is not called, the members of it (e.g. dptr) don't get
destructed. That way they have no chance to free up the memory
they allocated.
| Quote: | For example,
free in C, on wich delete is bases,
|
Nothing guarantees that delete invokes free. They are two
individual functionalities.
| Quote: | doesn't need to know the type, it can
even be a void *, as the standard heap allocator as information regarding
the ammount of memory it allocated starting at that address.
|
Other than delete, free does not call the destructor of its
argument. delete does, thus it needs to know the correct type.
Frank
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Mon Oct 04, 2004 7:23 pm Post subject: Re: Question about virtual destructors |
|
|
Frank Birbacher <bloodymir.crap (AT) gmx (DOT) net> wrote
| Quote: | Gustavo Guerra wrote:
My question is solely based on the fact that I don't need any
destructor at all, so there's no issue of calling the wrong
destructor.
Just because you didn't explicitly write a dtor, doesn't mean there
won't be any. The compiler automatically generates a default
destructor which will invoke the dtors of all members.
Since now in your example the dtor of the most derived class (XPTI) is
not called, the members of it (e.g. dptr) don't get destructed. That
way they have no chance to free up the memory they allocated.
|
But the problem has nothing to do with calling the correct destructor or
not. The problem is simply that if the static type of the pointer used
in delete does not correspond to the dynamic type of the actual object,
you have undefined behavior. In many cases, for example, the wrong
address will be passed to the operator delete function. Which could
easily cause a program crash, either immediately, or at some undefined
time in the future.
| Quote: | For example, free in C, on wich delete is bases,
Nothing guarantees that delete invokes free. They are two individual
functionalities.
|
True, but they tend to use the same, or similar algorithms. At any
rate, both the operator delete function and the free function must be
passed the exact address that was returned from the operator new
function or the malloc function. If the dynamic type of the object is
not the same as the static type, and the destructor is not virtual,
there's no way for the compiler to get this information.
| Quote: | doesn't need to know the type, it can even be a void *, as the
standard heap allocator as information regarding the ammount of
memory it allocated starting at that address.
Other than delete, free does not call the destructor of its
argument. delete does, thus it needs to know the correct type.
|
Again, it has nothing to do with destructors per se, although this is
another typical symptom of the undefined behavior. When I write:
Base* pb = new Derived ;
the compiler generates whatever code is necessary to change the physical
address, so pb points to the Base part of Derived, and not to the entire
Derived. When I do
delete pb ;
the compiler needs to reverse this conversion; it can only do so if it
can find out the actual most derived type, and it does this by means of
a virtual destructor.
--
James Kanze GABI Software http://www.gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
news Guest
|
Posted: Tue Oct 05, 2004 6:18 am Post subject: Re: Question about virtual destructors |
|
|
"Gustavo Guerra" <gmcg (AT) acm (DOT) org> wrote
| Quote: | My question is solely based on the fact that I don't need any destructor at
all, so there's no issue of calling the wrong destructor
|
It's not a issue of which destructor gets called. The presence of the virtual
destructor is a signal to the compiler that delete is being used polymorhically.
The wrong destructor being called is only one of the possible outcomes. The
wrong deallocation function may also be called or just about anything else.
It is UNDEFINED BEHAVIOR to do what you are doing.
The rule says you must pass the value to delete that is either the return
value (same type) of a prior new, or that value converted to a base class pointer, and
in the latter case, it must have a virtual destructor.
Also note, that delete[] doesn't have the base class option. You must pass
the same type value as you allocated with new[].
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|