473,856 Members | 1,850 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Prevent a parent object's destructor from being called?

Hello,

Say I create a class ("Child") that inherits from another class
("Parent"). Parent's destructor is not virtual. Is there a way I can
prevent Parent's destructor from being called when a Child object goes
out of scope?

Specifically, I am dealing with a C library that provides a function
that must be called to "destruct" a particular struct (this struct is
dynamically allocated by another provided function). To avoid memory
leaks, I created a class that inherits from std::auto_ptr<[the C
struct]>, and I gave it just a constructor and a destructor. The
destructor just calls the 3rd-party "destructor " function.
Unfortunately the problem is that std::auto_ptr's destructor is not
virtual.

If the answer to my above question is no, does anyone know of an
alternative simple solution? I'd prefer to not have to rewrite
auto_ptr when the only difference would be the destructor.

Thanks,
Squeamz
Oct 27 '05 #1
6 7970
Squeamz wrote:
If the answer to my above question is no, does anyone know of an
alternative simple solution? I'd prefer to not have to rewrite
auto_ptr when the only difference would be the destructor.


shared_ptr (part of the boost libraries) is a better alternative to
auto_ptr. It lets you specify a 'deleter' function - ie, a function
that is called when all references are released in order to delete the
object. It sounds like what you want:
http://www.boost.org/libs/smart_ptr/shared_ptr.htm

Oct 27 '05 #2
Squeamz wrote:
Hello,

Say I create a class ("Child") that inherits from another class
("Parent"). Parent's destructor is not virtual. Is there a way I can
prevent Parent's destructor from being called when a Child object goes
out of scope?
The virtual-ness of a destructor has no bearing here. All the
destructors of the base classes and any non-static members are
called automatically. There's nothing you can do to stop this.
Specifically, I am dealing with a C library that provides a function
that must be called to "destruct" a particular struct (this struct is
dynamically allocated by another provided function). To avoid memory
leaks, I created a class that inherits from std::auto_ptr<[the C
struct]>, and I gave it just a constructor and a destructor. The
destructor just calls the 3rd-party "destructor " function.
Unfortunately the problem is that std::auto_ptr's destructor is not
virtual.


What does the virtualness of have to do with it. The only thing a
virtual destructor does for you is make destructing through base
class destructors. auto_ptr isn't appropriate here for the purpose
anyhow. Auto_ptr calls delete on a single object. Since delete
appears to be inappropriate, I don't know why you are using it.

Here:
class Wrapper {
public:
Wrapper() {
cstruct = C_ConstructorFu nction();
}
~Wrapper() {
C_DestructorFun ction(cstruct);
}
// you need to define or disable copy constructor
// and assignement operators as well.
private:
CStruct* cstruct;
};
Oct 27 '05 #3
On Thu, 27 Oct 2005 18:41:40 -0400, Ron Natalie <ro*@spamcop.ne t>
wrote:
Squeamz wrote:
Hello,

Say I create a class ("Child") that inherits from another class
("Parent"). Parent's destructor is not virtual. Is there a way I can
prevent Parent's destructor from being called when a Child object goes
out of scope?
The virtual-ness of a destructor has no bearing here. All the
destructors of the base classes and any non-static members are
called automatically. There's nothing you can do to stop this.


Ah, you're right. For some reason I was under the impression that
only one destructor gets called if the base destructor is virtual.
Thanks for the info.
What does the virtualness of have to do with it. The only thing a
virtual destructor does for you is make destructing through base
class destructors. auto_ptr isn't appropriate here for the purpose
anyhow. Auto_ptr calls delete on a single object. Since delete
appears to be inappropriate, I don't know why you are using it.


Well, I tried to explain my reasoning. Aside from its use of
'delete', auto_ptr does everything I need here. I wanted to override
the only part of auto_ptr that uses delete. That's why I was using
it. Obviously my reasoning was flawed :).

Your suggestion works, of course, but like I said I didn't want to
have to deal with writing the assignment operator and stuff.

Anyway I think I'll take a look at boost's shared_ptr (thanks Pete!).

Squeamz
Oct 27 '05 #4
Squeamz wrote:
Hello,

Say I create a class ("Child") that inherits from another class
("Parent"). Parent's destructor is not virtual. Is there a way I can
Irrelevant; you aren't deleting a dynamic object through a base class
pointer.
prevent Parent's destructor from being called when a Child object goes
out of scope?
A Child object is a kind of Parent object. So a Parent is going out of
scope.

The destructor calls are linked, and that is not under programmer
control. The only way to break out of it would be to throw an exception
out of Child::~Child() . That's a bad idea; it would screw up other
things; don't do that.

I think you have to use aggregation here or composition rather than
inheritance. The Child class should have a reference to a Parent.
Specifically, I am dealing with a C library that provides a function
that must be called to "destruct" a particular struct (this struct is
dynamically allocated by another provided function). To avoid memory
leaks, I created a class that inherits from std::auto_ptr<[the C
struct]>, and I gave it just a constructor and a destructor.


The problem with this is that auto_ptr destructor will want to call
delete on whatever pointer is inside it. Inheritance won't fix this
behavior. The only way to prevent its destructor from doing that is to
steal that pointer!

In your own destructor, you take the managed pointer out of the
auto_ptr base class and replace it with null. Then if the pointer you
pulled out is non-null, you call the C library's destruction routine.
If the pointer is null, then the auto_ptr doesn't own any object; you
do nothing. But if you do this, what's the point of using auto_ptr? You
are rewriting half of its logic in your own derived class, which
defeats the point of inheritance.

Th eproblem

Here is how to do this silliness:

class MyClass : public auto_ptr<Whatev er> {
// ...
public:
// ...
~MyClass() {
try {
Whatever *purloined = release();

if (purloined != 0)
CLibraryDeleteF unction(purloin ed);
} catch (...) {
// release() threw because there is no pointer!
}
}
};

Some implementations of auto_ptr throw an exception in release() if the
object doesn't own any pointer; others just return null, that's why
there is the try/catch.

Get it? Your destructor is called first. It calls release() in the base
class, which takes ownership of the pointer out of auto_ptr and
replaces it it with null, and returns the original pointer. If the
return value is non-null it means that the object really did own
something, and so the C library routine can be called.

But with all that work, you might as well just complete the above class
to be a smart pointer in itself, and then get rid of the inheritance
from auto_ptr.

The right way with auto_ptr to take advantage of the second template
parameter in the smart pointer class! That template parameter lets you
specify a custom allocator class. There is a default value for that
parameter, so you don't have to deal with it most of the time: the
default value specifies a class that uses new/delete. You can write
your own allocator class that uses the C library's functions. There is
probably code somewhere you can cut and paste for this.

Another way to deal with this problem is to wrap a C++ management class
around the object. The C++ class's constructor and destructor call into
the C library's creation and deletion functions, respectively. A
pointer to the C object is kept inside this C++ object.

You can dynamically allocate the C++ object also, and use smart
pointers to manage that. Of course, there is no need for a special
allocator because you are using new/delete on the C++ object.

Oct 28 '05 #5
Squeamz wrote:
Ah, you're right. For some reason I was under the impression that
only one destructor gets called if the base destructor is virtual.
Thanks for the info.
The virtual destructor in the base ensures that the destructor call
through the base goes to the destructor of the most derived class, as
if that were called directly. From there, all the destructors are
called in the appropriate order over the entire inheritance lattice!
Well, I tried to explain my reasoning. Aside from its use of
'delete', auto_ptr does everything I need here. I wanted to override
the only part of auto_ptr that uses delete. That's why I was using
it. Obviously my reasoning was flawed :).


Normally, destructors just take care of clean-up at their level. The
reason destructors can be virtual is /not/ for the sake of overriding
base class behavior, as is the case with other virtual functions.

But you /can/ nervertheless override base class destructor behavior in
a derived class destructor. You just have to ensure that the base class
destructur somehow knows that it was done, so it does not try to
duplicate the job that was taken over, which would result in a
redundant or otherwise wrongful deallocation.

Oct 28 '05 #6
Squeamz wrote:
Well, I tried to explain my reasoning. Aside from its use of
'delete', auto_ptr does everything I need here. I wanted to override
the only part of auto_ptr that uses delete. That's why I was using
it. Obviously my reasoning was flawed :).
Other than delete, auto_ptr is just a pointer.
Your suggestion works, of course, but like I said I didn't want to
have to deal with writing the assignment operator and stuff.


All you need to do is:
private:
Wrapper(const Wrapper&); // Don't implement
Wrapper& operator=(const Wrapper&); // don't implement

This will make the object non-copyable in most cases, and should cause
a linker error for the missing functions in the few cases that don't

There's also a boost::non_copy able class you can mix in to do
the same thing (it's just a base class with the same construct that
"poisons" any object that contains it.
Oct 30 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

9
6239
by: Felix Wiemann | last post by:
Sometimes (but not always) the __new__ method of one of my classes returns an *existing* instance of the class. However, when it does that, the __init__ method of the existing instance is called nonetheless, so that the instance is initialized a second time. For example, please consider the following class (a singleton in this case): >>> class C(object): .... instance = None .... def __new__(cls): .... if C.instance is None:
3
6094
by: faktujaa | last post by:
Hi All, A small confusion. I have defined a connection class that has System.Data.IDbConnection as a member variable and implements IDisposable interface. I have implemented Dispose method to call Dispose method of IDbConnection. This Dispose method is called from a destructor. In the dispose method, i also call GC.SuppressFinalize(this) so as to avoid finalizer. All this was OK untill i came across one article that says - not to call...
3
1823
by: penny336 | last post by:
dear all, i am using vc++ 6.0 sp5 i have a class called Address,it allocated some memory space for streetname and city i first define it as Address add = new Address("Madrian","UK"); ... delete add // delete it explicitly
5
1783
by: August1 | last post by:
This is a short program that I have written from a text that demonstrates a class object variable created on the stack memory and another class object variable created on the heap memory. By way of the text, the program is supposed to demonstrate the use of a copy constructor function for the object created on the heap (because there is a char* pointer variable in the instantiated class) and how you would use the delete keyword with the...
2
1495
by: Vulcan Fire | last post by:
Hi Had this doubt really irking me for some time. For some obj of type say Obj. void fn(Obj o){ // do somethng }
9
2093
by: jon wayne | last post by:
OK! I had this nagging doubt Consider (without worrying abt access specifiers) class Kid : public Parent{...}; Parent::someFunc() { Kid k; }
5
3407
by: EqDev | last post by:
I have a class that is a control derived from UserControl. I want to use serialization and deserialization with this calss but I get an exception "Cannot serialize member System.ComponentModel.Component.Site of type System.ComponentModel.ISite because it is an interface.". I am not interested in serializing any member from the base class only the properties in the derived class. How can I prevent the entire base class from being...
6
3992
by: Sashi | last post by:
class parent{ Parent(){}; ~Parent(){}; } Child: public Parent{ Child(){}; ~Child(){};
2
2979
by: maynard | last post by:
I have defined a template class (tree data structure) that uses dynamic memory and has properly implemented ctor's, dtor and assignment operator. I can observe the address of my tree object prior to the destructor being called, and then the address once inside the destructor...they're different! The following calls are on the stack between the call to my destructor and the actual destructor itself: `eh vector destructor iterator'(void...
0
11081
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10709
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10806
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
10394
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
9544
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7939
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
7104
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
2
4189
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
3214
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.