My overridden function is not called!

Jul 7, 2011 at 1:20pm
I am trying to make a custom listener based on the observer pattern, like the listeners for Java.

I have this:
1
2
3
4
5
6
7
8
9
10
11
// eventlistener.h
#include <iostream>
using namespace std;

class EventListener
{
   public:
   EventListener(){};
   ~EventListener(){}
   virtual void action(){}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// dataclass.h
#include <iostream>
#include "customeventlistener.h"
using namespace std;

class DataClass
{
   private:
   list<EventListener> listeners;
   int value;
   void fireListeners()
   {
      list<EventListener>::iterator it;
      for(it=listeners.begin(); it!=listeners.end(); it++)
      {
          (*it).action();
      }
   }
  
   public: 
   void addCustomListener(EventListener listener)
   {
      listeners.push_back(listener);
   }

   void setValue(int val)
   {
      this->value = val;
      fireListeners();
   }
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//main.cpp
#include <iostream>
#include "dataclass.h"

using namespace std;

class Listener : public EventListener
{
   public: 
   void action()
   {
      cout << "Changed value!" << endl;
   }
};

int main()
{
   DataClass object;
   Listener listener;
   object.addCustomListener(listener);
   object.setValue(5);
   return 0;
}


With the above code I expect that the action() function in the Listener class (declared in main.cpp) shall be called since it is overridden.

But it is the action() function in EventListener that is beeing called.
What am I doing wrong?
Jul 7, 2011 at 1:30pm
You store copies of the listeners instead of pointers to them. Worse, you don't even store full copies, but just the EventListener part of them. This is called object slicing:
http://en.wikipedia.org/wiki/Object_slicing
Jul 7, 2011 at 1:40pm
agree upstair.
list<EventListener*> listeners;
....................................

object.addCustomListener(&listener);
.............................................

you should use the pionter to archive your idea。。。。。。。。。
Jul 7, 2011 at 6:33pm
Thanks for the link Athar Ive never heard of object slicing
Jul 8, 2011 at 6:03am
Ok, I got it working by storing the objects as pointers.

I also tried to change line 21 in dataclass.h to:
void addCustomListener(EventListener *listener)
and line 19 in main.cpp to:
Listener *listener;

When I run the program, I get a segmentation fault for line 16 in dataclass.h
(*it)->action();

I am trying to understand why, but I cannot. So, why?
Jul 8, 2011 at 6:52am
It should work if you only changed these three lines (and object.addCustomListener(&listener);).
However, note that with your current approach DataClass will never know when one of the listeners has been destroyed.
Also, the EventListener destructor should be virtual. If it isn't, deleting a derived listener via a EventListener pointer would result in undefined behavior.
Jul 8, 2011 at 8:11am
Thanks!

I have done a third class, called customevent.h:
1
2
3
4
5
6
7
8
9
10
11
// customevent.h
class CustomEvent
{
   private:
   DataClass dc;

   public:
   CustomEvent(){};
   ~CustomEvent(){}
   void getObject(){}
}


I have also changed EventListener to:
1
2
3
4
5
6
7
8
9
10
11
12
// eventlistener.h
#include <iostream>
#include "customevent.h"
using namespace std;

class EventListener
{
   public:
   EventListener(){};
   ~EventListener(){}
   virtual void action(CustomEvent*){} // the changed line
}


In dataclass.h, I now have this:
1
2
3
4
5
6
7
8
9
void fireListeners()
   {
      CustomEvent event; // added line
      list<EventListener>::iterator it;
      for(it=listeners.begin(); it!=listeners.end(); it++)
      {
          (*it).action(&event); // changed line
      }
   }


My problem: CustomEvent cannot find DataClass. If I include dataclass.h in customevent.h, then it won´t compile because DataClass includes customeventlistener.h which in turn includes customevent.h. So the three files includes each other in a circle-like manner.

How can I work around this?
Last edited on Jul 8, 2011 at 8:14am
Jul 8, 2011 at 9:15am
Forward declare one of the classes and then include them in the .cpp file defining the functions
Topic archived. No new replies allowed.