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 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?
"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
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
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
"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
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
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
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);
}
};
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 This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
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"...
|
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...
|
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.
...
|
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) .
|
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...
| |
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...
|
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...
|
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()
|
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...
|
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,...
|
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...
| |
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,...
|
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...
|
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...
|
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...
|
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
|
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 ...
| |
by: muto222 |
last post by:
How can i add a mobile payment intergratation into php mysql website.
| |