473,473 Members | 1,510 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

Force method call in destructor of a derived class?

Hello!

I have written two template classes which implement the observerpattern
in C++. I hope I manage to desribe the problem I have.

template<class T> class Observer {
/* ... */
};

template<class T> classSubject {
/* ... */
};

These template classes are being used as base classes for non abstract
Observer and Subject classes. The update() method in the observer class
is pure virtual and needs to be implemented by the class which derives
the Observer template class. This is good, because the user can't forget
to implement it.

In my concept the subject has a list of attached observers, and the
Observer has a list of subject it was attached to. When a observer is
destructed for some reason, the destructor detaches itself from all
Subjects it was attached to.

Now my problem: At that point, when I am in the destructor of the
Observer template, the update method isn't available anymore. (Because
the derived class is already destructed) So in case the Subject now
tries to notify the observer the application crashes. Of course this
only happens with a multithreaded application. In normal case this
condition will happen very very seldom. But it can and will happen some
day. I have found two ways to resolve this issue. I don't like one of them.

1. Make the method update() in the observer base class virtual only
(defining an empty body). The user isn't forced anymore to implement
update in the derived class of the Observer pattern and might forget it.

2. By forcing the user to call some method from the destructor of the
derived class which was defined in the Observer base class which
detaches itself from all Subjects. The user may forget to insert this
call in his destructor and we have the problem again.

Anyone knows a third way to resolve my problem? I hope I managed to
describe my problem... :D If not, then just ignore it and i am lost... *g*

Have a nice day,
Daniel
Sep 22 '05 #1
9 3642
* Daniel Kay:
[long problem description]


The short of it seems to be: you need some notification when the client code's
derived class object is destroyed.

And one way to do that is to force the client code to use a special template
class as the most derived class.

Client code:

class MyObserverImpl: public Observer { ... };
typedef ConcreteObserver<MyObserverImpl> MyObserver;

where ConcreteObserver is a template class you provide, where the destructor
provides the notification you need.

You can force use of ConcreteObserver via the virtual base class with private
constructor and friend trick, described in the FAQ for the case of disallowing
further inheritance -- making a class "final" or "sealed" -- but I think
more useful for the case above, forcing a given most derived class.

One main problem with this technique is how to forward constructor arguments
from ConcreteObserver to, in the example above, MyObserverImpl. And one
solution is to require that every constructor except the default constructor
must have exactly one argument (which can be a struct), and then use a
templated constructor. There are also other solutions.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Sep 22 '05 #2
"Daniel Kay" <da********@arcor.de> wrote in message
news:43********************@newsread2.arcor-online.net...
Hello!

I have written two template classes which implement the observerpattern
in C++. I hope I manage to desribe the problem I have.

template<class T> class Observer {
/* ... */
};

template<class T> classSubject {
/* ... */
};

These template classes are being used as base classes for non abstract
Observer and Subject classes. The update() method in the observer class
is pure virtual and needs to be implemented by the class which derives
the Observer template class. This is good, because the user can't forget
to implement it.

In my concept the subject has a list of attached observers, and the
Observer has a list of subject it was attached to. When a observer is
destructed for some reason, the destructor detaches itself from all
Subjects it was attached to.

Now my problem: At that point, when I am in the destructor of the
Observer template, the update method isn't available anymore. (Because
the derived class is already destructed) So in case the Subject now
tries to notify the observer the application crashes. Of course this
only happens with a multithreaded application. In normal case this
condition will happen very very seldom. But it can and will happen some
day. I have found two ways to resolve this issue. I don't like one of them.
1. Make the method update() in the observer base class virtual only
(defining an empty body). The user isn't forced anymore to implement
update in the derived class of the Observer pattern and might forget it.

2. By forcing the user to call some method from the destructor of the
derived class which was defined in the Observer base class which
detaches itself from all Subjects. The user may forget to insert this
call in his destructor and we have the problem again.

Anyone knows a third way to resolve my problem? I hope I managed to
describe my problem... :D If not, then just ignore it and i am lost... *g*

Have a nice day,
Daniel


You shouldn't allow other threads to invoke member functions on an object
that is destructing unless you have a guarantee from your implementation
that the "behind the scenes" work that your implementation provides for
destruction is thread-safe. Your implementation may be messing with the
vtable or doing other things when you invoke one of the functions. You
should remove the observer from the subject before object destruction
begins.

--
David Hilsee
Sep 22 '05 #3
Alf P. Steinbach wrote:
* Daniel Kay:
[long problem description]

The short of it seems to be: you need some notification when the client code's
derived class object is destroyed.

And one way to do that is to force the client code to use a special template
class as the most derived class.

Client code:

class MyObserverImpl: public Observer { ... };
typedef ConcreteObserver<MyObserverImpl> MyObserver;

where ConcreteObserver is a template class you provide, where the destructor
provides the notification you need.

You can force use of ConcreteObserver via the virtual base class with private
constructor and friend trick, described in the FAQ for the case of disallowing
further inheritance -- making a class "final" or "sealed" -- but I think
more useful for the case above, forcing a given most derived class.

One main problem with this technique is how to forward constructor arguments
from ConcreteObserver to, in the example above, MyObserverImpl. And one
solution is to require that every constructor except the default constructor
must have exactly one argument (which can be a struct), and then use a
templated constructor. There are also other solutions.


Thank you for your spare time on giving me some idea on how to solve my
problem. If no better solutions is being posted I'll try to implement it.

Thx,
Daniel
Sep 22 '05 #4
David Hilsee wrote:
"Daniel Kay" <da********@arcor.de> wrote in message
news:43********************@newsread2.arcor-online.net...
Hello!

I have written two template classes which implement the observerpattern
in C++. I hope I manage to desribe the problem I have.

template<class T> class Observer {
/* ... */
};

template<class T> classSubject {
/* ... */
};

These template classes are being used as base classes for non abstract
Observer and Subject classes. The update() method in the observer class
is pure virtual and needs to be implemented by the class which derives
the Observer template class. This is good, because the user can't forget
to implement it.

In my concept the subject has a list of attached observers, and the
Observer has a list of subject it was attached to. When a observer is
destructed for some reason, the destructor detaches itself from all
Subjects it was attached to.

Now my problem: At that point, when I am in the destructor of the
Observer template, the update method isn't available anymore. (Because
the derived class is already destructed) So in case the Subject now
tries to notify the observer the application crashes. Of course this
only happens with a multithreaded application. In normal case this
condition will happen very very seldom. But it can and will happen some
day. I have found two ways to resolve this issue. I don't like one of


them.
1. Make the method update() in the observer base class virtual only
(defining an empty body). The user isn't forced anymore to implement
update in the derived class of the Observer pattern and might forget it.

2. By forcing the user to call some method from the destructor of the
derived class which was defined in the Observer base class which
detaches itself from all Subjects. The user may forget to insert this
call in his destructor and we have the problem again.

Anyone knows a third way to resolve my problem? I hope I managed to
describe my problem... :D If not, then just ignore it and i am lost... *g*

Have a nice day,
Daniel

You shouldn't allow other threads to invoke member functions on an object
that is destructing unless you have a guarantee from your implementation
that the "behind the scenes" work that your implementation provides for
destruction is thread-safe. Your implementation may be messing with the
vtable or doing other things when you invoke one of the functions. You
should remove the observer from the subject before object destruction
begins


Hello David!

Right now the destructor of the observer base class does the following
to protect itself from calling subjects.

Make sure that all subjects the observer is attached to won't try to
call the update() method by invoking the lock() method of all subject
instances. Then I detach from all subjects. Then I invoke unlock() for
all subjects, so they can continue their work.

The time between destructing the derived instance and locking all
subjects is critical. Of course one solution is to call a method defined
in the observer base class before I destruct the derived class. But
there must be a better way in resolving this problem.

Bye,
Daniel Kay
Sep 22 '05 #5
"Daniel Kay" <da********@arcor.de> wrote in message
news:43***********************@newsread4.arcor-online.net...
[...]

Hello David!

Right now the destructor of the observer base class does the following
to protect itself from calling subjects.

Make sure that all subjects the observer is attached to won't try to
call the update() method by invoking the lock() method of all subject
instances. Then I detach from all subjects. Then I invoke unlock() for
all subjects, so they can continue their work.

The time between destructing the derived instance and locking all
subjects is critical. Of course one solution is to call a method defined
in the observer base class before I destruct the derived class. But
there must be a better way in resolving this problem.


OK, I just wanted to make sure that you understood that "solution" #1
suffers from multithreading issues.

I suppose you could always write a little handle class that holds on to the
observer and does the work for you. In its destructor, you could detach the
observer from the subjects before you destruct the object. Then you always
hold on to observers using that wrapper class instead of just using the
Observer class.

class ObserverHandle {
Observer * observer;

//...
~ObserverHandle() {
observer->DetachFromSubjects();
delete observer;
}
};

--
David Hilsee
Sep 23 '05 #6

Daniel Kay wrote:
Hello!

I have written two template classes which implement the observerpattern
in C++. I hope I manage to desribe the problem I have.

template<class T> class Observer {
/* ... */
};

template<class T> classSubject {
/* ... */
};

These template classes are being used as base classes for non abstract
Observer and Subject classes. The update() method in the observer class
is pure virtual and needs to be implemented by the class which derives
the Observer template class. This is good, because the user can't forget
to implement it.

In my concept the subject has a list of attached observers, and the
Observer has a list of subject it was attached to. When a observer is
destructed for some reason, the destructor detaches itself from all
Subjects it was attached to.

Now my problem: At that point, when I am in the destructor of the
Observer template, the update method isn't available anymore. (Because
the derived class is already destructed) So in case the Subject now
tries to notify the observer the application crashes. Of course this
only happens with a multithreaded application. In normal case this
condition will happen very very seldom. But it can and will happen some
day. I have found two ways to resolve this issue. I don't like one of them.

1. Make the method update() in the observer base class virtual only
(defining an empty body). The user isn't forced anymore to implement
update in the derived class of the Observer pattern and might forget it.

2. By forcing the user to call some method from the destructor of the
derived class which was defined in the Observer base class which
detaches itself from all Subjects. The user may forget to insert this
call in his destructor and we have the problem again.

Anyone knows a third way to resolve my problem? I hope I managed to
describe my problem... :D If not, then just ignore it and i am lost... *g*

Have a nice day,
Daniel


Why not implement Observer::Update() but keep it a pure virtual
function so subclasses still have to implement it themselves?

Greg

Sep 23 '05 #7
Greg wrote:
Daniel Kay wrote:
Hello!

I have written two template classes which implement the observerpattern
in C++. I hope I manage to desribe the problem I have.

template<class T> class Observer {
/* ... */
};

template<class T> classSubject {
/* ... */
};

These template classes are being used as base classes for non abstract
Observer and Subject classes. The update() method in the observer class
is pure virtual and needs to be implemented by the class which derives
the Observer template class. This is good, because the user can't forget
to implement it.

In my concept the subject has a list of attached observers, and the
Observer has a list of subject it was attached to. When a observer is
destructed for some reason, the destructor detaches itself from all
Subjects it was attached to.

Now my problem: At that point, when I am in the destructor of the
Observer template, the update method isn't available anymore. (Because
the derived class is already destructed) So in case the Subject now
tries to notify the observer the application crashes. Of course this
only happens with a multithreaded application. In normal case this
condition will happen very very seldom. But it can and will happen some
day. I have found two ways to resolve this issue. I don't like one of them.

1. Make the method update() in the observer base class virtual only
(defining an empty body). The user isn't forced anymore to implement
update in the derived class of the Observer pattern and might forget it.

2. By forcing the user to call some method from the destructor of the
derived class which was defined in the Observer base class which
detaches itself from all Subjects. The user may forget to insert this
call in his destructor and we have the problem again.

Anyone knows a third way to resolve my problem? I hope I managed to
describe my problem... :D If not, then just ignore it and i am lost... *g*

Have a nice day,
Daniel

Why not implement Observer::Update() but keep it a pure virtual
function so subclasses still have to implement it themselves?


I don't understand...

class PureVirtualMethod {
virtual void update(Subject* s) = 0;
};

class VirtualMethod {
virtual void update(Subject* s) { };
};

I am not forced to define an own version of update(Subject* s) with the
second class. Or is there any way to define it in the base class but
also force the user to define his own? Would be new to me.

Today I had a look at the boost libraries. And I had a look at
signal/slot template which seems simular to the technique used by QT.
Maybe that's the solution for my problem. Thanks to everyone...

Cya,
Daniel Kay
Sep 23 '05 #8
Daniel Kay wrote:

class PureVirtualMethod {
virtual void update(Subject* s) = 0;
};


As I understand it, the following is legal;

class PureVirtualMethod {
public:
virtual void update(Subject* s) = 0;
};

void PureVirtualMethod::update(Subject* s)
{
// some implementation
}

class NonPure : public PureVirtualMethod
{
public:
void update(Subject* s)
{
// my implementation specific details here
// followed by common code
PureVirtualMethod::update(s);
}
};

Sep 23 '05 #9
Daniel Kay wrote:
Greg wrote:
Daniel Kay wrote:
Hello!

I have written two template classes which implement the observerpattern
in C++. I hope I manage to desribe the problem I have.

template<class T> class Observer {
/* ... */
};

template<class T> classSubject {
/* ... */
};

These template classes are being used as base classes for non abstract
Observer and Subject classes. The update() method in the observer class
is pure virtual and needs to be implemented by the class which derives
the Observer template class. This is good, because the user can't forget
to implement it.

In my concept the subject has a list of attached observers, and the
Observer has a list of subject it was attached to. When a observer is
destructed for some reason, the destructor detaches itself from all
Subjects it was attached to.

Now my problem: At that point, when I am in the destructor of the
Observer template, the update method isn't available anymore. (Because
the derived class is already destructed) So in case the Subject now
tries to notify the observer the application crashes. Of course this
only happens with a multithreaded application. In normal case this
condition will happen very very seldom. But it can and will happen some
day. I have found two ways to resolve this issue. I don't like one of them.

1. Make the method update() in the observer base class virtual only
(defining an empty body). The user isn't forced anymore to implement
update in the derived class of the Observer pattern and might forget it.

2. By forcing the user to call some method from the destructor of the
derived class which was defined in the Observer base class which
detaches itself from all Subjects. The user may forget to insert this
call in his destructor and we have the problem again.

Anyone knows a third way to resolve my problem? I hope I managed to
describe my problem... :D If not, then just ignore it and i am lost... *g*

Have a nice day,
Daniel

Why not implement Observer::Update() but keep it a pure virtual
function so subclasses still have to implement it themselves?


I don't understand...

class PureVirtualMethod {
virtual void update(Subject* s) = 0;
};

class VirtualMethod {
virtual void update(Subject* s) { };
};

I am not forced to define an own version of update(Subject* s) with the
second class. Or is there any way to define it in the base class but
also force the user to define his own? Would be new to me.


I bet that you would not be the only C++ programmer to be surprised by
the fact that pure virtual functions can be defined. In fact, sometimes
a pure virtual function must be defined, according to the Standard:

A pure virtual function need be defined only if
explicity called with the qualified-id syntax. [10.4.2]

In other words, if Observer::update() is called explicitly from
anywhere than that pure virtual function must be defined. Otherwise
defining it is optional. Since the program is crashing because
Observer::update is not defined, defining Observer::update() should fix
the crash with only three lines of empty code:

void Observer::update()
{
// do nothing
}

Note that the pure virtual syntax prevents the definition and the
declaration from being combined. So the definition of a pure virtual
function must always appear on its own.

In fact a pure virtual function can override a non-pure function in a
base class. So Observer could inherit from a base class with a nonpure
update() that it would override with a pure update(). But it is simpler
just for Observer to implement update() itself as a pure virtual
function, than to implement a more complicated solution.

Greg

Sep 24 '05 #10

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

Similar topics

11
by: Stub | last post by:
Please answer my questions below - thanks! 1. Why "Derived constructor" is called but "Derived destructor" not in Case 1 since object B is new'ed from Derived class? 2. Why "Derived destructor"...
7
by: Calvin Lai | last post by:
Hi all, I have a simple question. If I have a ClassA as base class, and ClassB derive from it. There is a virtual function foo() in ClassA, and in Class B, I defined a function called foo() as...
23
by: ctick | last post by:
A reason for declaring a "virtual destructor" for a Base class is to make sure the destructor of Derived class will be invoked when a pointer of Base type is used to delete an object of Derived. ...
23
by: Fabian Müller | last post by:
Hi all, my question is as follows: If have a class X and a class Y derived from X. Constructor of X is X(param1, param2) . Constructor of Y is Y(param1, ..., param4) .
26
by: pmizzi | last post by:
When i compile my program with the -ansi -Wall -pedantic flags, i get this warning: `class vechile' has virtual functions but non-virtual destructor, and the same with my sub-classes. But when i...
7
by: Christopher Wells | last post by:
There's something I don't understand about how the CollectionBase class is defined. I can declare: class Derived : CollectionBase { } I can instantiate this Derived class: Derived derived...
6
by: pragtideep | last post by:
I am trying to understand the following code kindly help me #include<iostream> using namespace std; class base { private: ~base() {cout << "This is base destructor"<<endl ;} friend class...
3
by: a | last post by:
Hi, I need clarification for virtual method and pure virtual method. e.g Class Base{ virtual void func(){ ---- } } Class Child : public Base{ void func()
8
by: lmfmaw | last post by:
Hi all, I've hit the wall with this "fairly" simple problem. As you can see in the code below, my destructors don't do their job as they are supposed to (I left them empty for this example). I'm...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
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,...
0
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...
1
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...
0
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...
0
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
0
muto222
php
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

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.