Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Some questions from a n00b

64 views
Skip to first unread message

Robert Hutchings

unread,
Oct 18, 2014, 10:32:33 AM10/18/14
to
Given this code:

#include <iostream>
#include <set>

using namespace std;

// ---------------- Observer interface -----------------
class Observer {
public:
virtual void Notify() = 0;
};

// ---------------- Observable object -------------------
class Observable {
static Observable* instance;
set<Observer*> observers;
Observable() { };
public:
static Observable* GetInstance();
void AddObserver(Observer& o);
void RemoveObserver(Observer& o);
void NotifyObservers();
void Trigger();
};

Observable* Observable::instance = NULL;

Observable* Observable::GetInstance()
{
if (instance == NULL) {
instance = new Observable();
}

return instance;
}

void Observable::AddObserver(Observer& o)
{
observers.insert(&o);
}

void Observable::RemoveObserver(Observer& o)
{
observers.erase(&o);
}

void Observable::NotifyObservers()
{
set<Observer*>::iterator itr;
for (itr = observers.begin();
itr != observers.end(); itr++)
(*itr)->Notify();
}

// TEST METHOD TO TRIGGER
// IN THE REAL SCENARIO THIS IS NOT REQUIRED
void Observable::Trigger()
{
NotifyObservers();
}

// ------ Concrete class interested in notifications ---
class MyClass : public Observer {

Observable* observable;

public:
MyClass() {
observable = Observable::GetInstance();
observable->AddObserver(*this);
}

~MyClass() {
observable->RemoveObserver(*this);
}

void Notify() {
cout << "Received a change event" << endl;
}
};



void main()
{
Observable* observable = Observable::GetInstance();
MyClass* obj = new MyClass();
observable->Trigger();
}



What if I don't to use a SET? What is the advantage of using pointers
with "new", as apposed to NOT using pointers?

Paavo Helde

unread,
Oct 18, 2014, 10:49:12 AM10/18/14
to
Robert Hutchings <rm.hut...@gmail.com> wrote in news:m1ttlj$3m3$1
@dont-email.me:
Whic pointers exactly? You have a lot of them here.

"MyClass* obj = new MyClass()" is not needed (and you have a memory leak
caused by it), you could do equally well

MyClass obj;

Dynamic allocation is needed only if the lifetime of the object is not
bound to a single scope.

You also have a lot of pointers to Observable. Most of them could be
replaced by a reference for a bit better syntax.

You don't need the member variable MyClass::observable, instead you can
call Observable::GetInstance() whenever needed.

But inside the Observable, you need a std::set or some other container of
pointers though (because you cannot put references into a container, as
they are not objects, unlike pointers).


hth
Paavo




Robert Hutchings

unread,
Oct 18, 2014, 11:07:53 AM10/18/14
to
OK, thanks for that Paavo.

Öö Tiib

unread,
Oct 18, 2014, 4:12:40 PM10/18/14
to
On Saturday, 18 October 2014 17:32:33 UTC+3, Robert Hutchings wrote:
> Given this code:
>
> #include <iostream>
> #include <set>
>
> using namespace std;

That line I don't write.
Never write 'void main()' in C or C++ forums without mentioning compiler
that you target. It is compiler-specific extension. Standard only
defines 'int main()'.

> {
> Observable* observable = Observable::GetInstance();
> MyClass* obj = new MyClass();
> observable->Trigger();
> }
>
>
> What if I don't to use a SET? What is the advantage of using pointers
> with "new", as apposed to NOT using pointers?

'std::set' seems fine. If you want an alternative sorted value container
that performs differently (and often wins 'std::set' in performance) then
you should perhaps try 'boost::flat_set'. Some shops use it always where a
set is needed.

The problem is not in raw pointers (despite I next to never use these in
C++ and all is fine). The problem is that your observer pattern has passed
the responsibility of management of those (raw pointer) bindings to user
classes. You do it probably by some book? Toss it away, it does not discuss
the issues under hand in enough depth.

For example your 'Observer' class does not have capability to know what
(if anything) it observes. As result the knowledge is in 'MyClass' and so
the responsibility to manage the binding between itself and 'Observable'
is given to 'MyClass'. Why? That results in copy-paste implementation
of binding (raw pointer) management in all classes derived from 'Observer'.

Also your design contains some serious constraints.
Your 'Observable' (usually called "Subject" in books) is a first demand
singleton with never ending lifetime in your design. That is seriously
limiting. The 'MyClass' can handle only one thing with its 'Notify()'
from that global single 'Observable'. That is also rather limiting. Such
limits narrow the usefulness of it and so the amount of practical problems
for what it may be is good enough.

'Observable' could have responsibility to call some "detach from me" of all
its observers from its destructor and so have normal life-time that is
not bound to observers. Bindings can be made in lot more generic ways
so different notifications can be received from different subjects thru
different handlers.

Have you considered of looking at existing art? The source code may
be hard to understand for beginner (too generic, too thread-safe) but
reading documentation and examples and trying to use these things may move
you closer to understanding of the power of that important pattern and also
aid to see the volume of problems that it can solve.

For concrete examples take some sigslot by Sarah Thompson from sourceforge http://sigslot.sourceforge.net/ Alternatively Leigh made and published
his 'neosigslot' some time ago here http://i42.co.uk/stuff/neosigslot.htm
Leigh is trolling here as "Mr Flibble", but don't worry, C++ he knows well
and can write finely.

If you want more heavyweight examples (in sense of code size, the
performance is fine) then download Boost libraries and look at
Boost.Signals2 or take GTK and its C++ wrapper contains one. Also it is
may be worth to note that Qt generates such slots and signals binding
code with its 'moc' preprocessor, so there's no point of such classes if
you use Qt framework.

Robert Hutchings

unread,
Oct 18, 2014, 4:15:45 PM10/18/14
to
OK, I will check these out. Thanks very much. Yes, I got this from a
book....

Mr Flibble

unread,
Oct 18, 2014, 4:45:15 PM10/18/14
to
On 18/10/2014 21:12, 嘱 Tiib wrote:

> For concrete examples take some sigslot by Sarah Thompson from sourceforge http://sigslot.sourceforge.net/ Alternatively Leigh made and published
> his 'neosigslot' some time ago here http://i42.co.uk/stuff/neosigslot.htm
> Leigh is trolling here as "Mr Flibble", but don't worry, C++ he knows well
> and can write finely.

Don't break the fourth wall!

/Flibble

P.S. Sausages.

Juha Nieminen

unread,
Oct 20, 2014, 9:16:53 AM10/20/14
to
Robert Hutchings <rm.hut...@gmail.com> wrote:
> Given this code:

You are leaking memory all over the place.

Don't use 'new'.

If you really, really, really need to use it (iow. you actually have
an inheritance hierarchy and you need to handle objects by
pointer-to-base-class), then use smart pointers. But in general,
don't use 'new'.

--- news://freenews.netfront.net/ - complaints: ne...@netfront.net ---
0 new messages