communicate a class with testApp - via ofEvents?

Hello!

I’ve been trying for a while to get a class to communicate with testApp. It’s been no problem using the “advancedEventsExample” to send events to the testApp; however, whenever I try to create a class that inherits from the “eventsObject” provided in the example, or when I simply try to add an ofEvent to my class, I get the following error:

  
  
../../../libs/poco/include/Poco/FIFOEvent.h|82|error: ‘Poco::FIFOEvent<TArgs>::FIFOEvent(const Poco::FIFOEvent<TArgs>&) [with TArgs = int]’ is private|  
  

Other than using this new poco events model, I can’t think of any other possibility to get my objects talking with testApp. I am trying to create simple buttons that when clicked]/dragged/etc. send values to testApp.

Thanks for your time, any pointers would be appreciated!

Rodrigo

Some poco classes like the events have a private constructor, that means that you cannot make a copy of any class containing an event.

If you have a class that contains an event and try to store it for example in a vector or pass it to a function you will get that error.

To solve it you’ll need to use pointers or references.

for example if you want to pass your class as a parameter of a function, instead of:

  
void myFunction(myClass object);  

you need to do:

  
void myFunction(myClass & object);  

Thanks Arturo!

Your info was really good; I am actually in need of using vectors for my project. So thanks to your tip I got it working.

The trickiest part is the declaration of the vector, and its implementation:

  
  
//declaration:  
std::vector<eventSender*> objectArray;  
  
//creation of the objects inside the vector, and the activation of their event listeners:  
    for(int i = 0 ; i<10; i++) {  
        objectArray.push_back(new eventSender(100+60*i,100,30,i));  
        objectArray[i]->enable();  
        ofAddListener(objectArray[i]->sendValue,this,&testApp::receiveValue);  
    }  
  
  

I decided to post the code in case somebody finds him/herself in the same situation as I was today…

Thanks again, and wow, the poco events are really amazing once you get the grasp of it…

Cheers!
Rodrigo

code:

class declaration:

  
class eventSender{  
    public:  
    eventSender(int _x, int _y, int _s, int _id)   {  
        x=_x;  
        y=_y;  
        s=_s;  
        id=_id;  
    }  
  
    void draw() {  
        ofCircle(x,y,s);  
    }  
  
    int x,y,s,id;  
  
    void enable(){  
        ofAddListener(ofEvents.mouseMoved, this, &eventSender::mouseMoved);  
    }  
  
    void mouseMoved(ofMouseEventArgs & args)    {  
        int d = sqrt(pow(x-args.x,2)+pow(y-args.y,2));  
        if(d<s)  
            ofNotifyEvent(sendValue,id,this);  
    }  
  
    ofEvent<int> sendValue;  
  
};  

testApp.h:

  
  
#ifndef _TEST_APP  
#define _TEST_APP  
  
class testApp : public ofBaseApp{  
  
	public:  
  
		void setup();  
		void update();  
		void draw();  
  
		void keyPressed(int key);  
		void keyReleased(int key);  
		void mouseMoved(int x, int y );  
		void mouseDragged(int x, int y, int button);  
		void mousePressed(int x, int y, int button);  
		void mouseReleased(int x, int y, int button);  
		void windowResized(int w, int h);  
  
		void receiveValue(int & i);  
  
                std::vector<eventSender*> objectArray;  
  
		string msg;  
  
};  
  
#endif  
  

testApp.cpp:

  
#include "testApp.h"  
#include "Poco/Delegate.h"  
#include "Poco/Timestamp.h"  
//--------------------------------------------------------------  
void testApp::setup(){  
	  
    for(int i = 0 ; i<10; i++) {  
        objectArray.push_back(new eventSender(100+60*i,100,30,i));  
        objectArray[i]->enable();  
        ofAddListener(objectArray[i]->sendValue,this,&testApp::receiveValue);  
    }  
}  
  
  
//--------------------------------------------------------------  
void testApp::update(){  
}  
  
//--------------------------------------------------------------  
void testApp::draw(){  
	ofDrawBitmapString(msg,20,20);  
	for(int i=0; i<objectArray.size(); i++)  
        objectArray[i]->draw();  
  
}  
  
//--------------------------------------------------------------  
void testApp::receiveValue(int & i){  
	msg	 	= "valueReceived:  " + ofToString(i);  
}  
  

Oh!
I forgot to ask:

when I want to delete the objects inside the vector, what is the best way? Would vector::erase() suffice? or would i explicitly have to call “delete” on the objects? Supposedly vectors take care of garbage collection; but in this case I’m explicitly creating a vector of pointers, so I don’t know anymore…

I’m not really sure, and would hate to ignore a memory leak…

Thanks again,
Rodrigo

when you call erase you are just deleting what is in the vector, in this case the pointers not the objects, so first you’ll need to delete all the objects with a for loop and then erase the vector.

as a general rule, whenever you call new, you’ll need to call delete, no matter where you store the objects

So, for complete delete an array of pointers i have to do something like this:

  
  
void delete(){  
    for (vector<Ball*>::const_iterator member = objectArray.begin(); member != objectArray.end(); member++)  
        delete *member;  
    objectArray.clear();  
}  
  

?

And if i want to remove all the events what i can do? I can write something like that?

  
  
int size = objectArray.size();  
for(int a = 0; a < size; a++)  
{  
    ofRemoveListener(balls[a]->sendValue, this, &testApp::receiveValue);  
    delete objectArray[a];  
}  
objectArray.clear();  
  

How can i write the some thing using const_iterator? I tried but i had some problems.

That will remove all the events and the call to delete *member will delete the pointer that it’s pointing to. Is there a reason you want to use const_iterator instead of an iterator?

Really maybe i am little bit confused about vector.
I see that “const_iterator” get a const element, so, i can get the element but i can’t change values of that element, right?
If it’s right, i can do “delete *member” but maybe is better to use a simple iterator?

I write my example and i have write those solution for clean the vector ( i use balls vector for my example, but it’s the same ):

  
  
for (vector<Ball*>::const_iterator member = balls.begin(); member != balls.end(); member++)  
    {  
        ofRemoveListener((*member)->hitBorder, this, &testApp::hitBordersHandler);  // hitBorder is my ofEventArgs class  
        delete *member;  
    }  
balls.clear();  
  

  
  
for (vector<Ball*>::iterator member = balls.begin(); member != balls.end(); member++)  
    {  
        ofRemoveListener((*member)->hitBorder, this, &testApp::hitBordersHandler);  
        delete *member;  
    }  
    balls.clear();  
  

  
  
int size = balls.size();  
    for(int a = 0; a < size; a++)  
    {  
        ofRemoveListener(balls[a]->hitBorder, this, &testApp::hitBordersHandler);  
        delete balls[a];  
    }  
    balls.clear();  
  

Or there are others solution?

And… sorry if i have many questions but i want to understand. :slight_smile:
So… if i write:

  
  
for (vector<Ball*>::const_iterator member = balls.begin(); member != balls.end(); member++)  
    {  
        cout << "***" <<endl;  
        cout << &(member) << endl;  
        cout << (*member) << endl;  
        ofRemoveListener((*member)->hitBorder, this, &testApp::hitBordersHandler);  
        delete *member;  
        cout << "*" <<endl;  
        cout << &(member) << endl;  
        cout << (*member) << endl;  
    }  
    balls.clear();  
  

My output is:

  
  
***  
0xbffff240  
0x785170  
*  
0xbffff240  
0x785170  
***  
0xbffff240  
0x784f80  
*  
0xbffff240  
0x784f80  
***  
0xbffff240  
0x788160  
*  
0xbffff240  
0x788160  
***  
0xbffff240  
0x7881f0  
*  
0xbffff240  
0x7881f0  
***  
0xbffff240  
0x788280  
*  
0xbffff240  
0x788280  
  

And when i create my 5 balls, their address are:

  
  
0x785170  
0x784f80  
0x788160  
0x7881f0  
0x788280  
  

So… i think 0xbffff240 is the address of my iterator… and it’s always the same, right?
And i don’t understand why after delete member i always see the same address for my member. It wouldn’t be… ehmm… NULL… or something different?

You’re not deleting the pointer, you’re deleting what it points to. If you want to delete the pointer you can use erase() or you can re-assign the pointer. Keep in mind though that if you don’t delete what the pointer is pointing at first (i.e. your Ball that you made with new) then you’re leaking it.

Read this: http://stackoverflow.com/questions/891913/c-stdvector-of-pointers-deletion-and-segmentation-faults

So… when i write "delete *member; " i free space on my memory and my pointer still point to some address, but that address is empty?
In my example i can write “(*member) = NULL;” or “(*member) = 0” and it’s all right?

If you’re using the const_iterator, no, if you’re using iterator, yes.

Sorry, you’re right! I forgot to write it. :slight_smile:
Thanks a lot, now it’s all more clear, but i think i have to read again the link you post and also this:

http://www.cplusplus.com/doc/tutorial/pointers/

Pointer are really hard but very interesting.