Laurens Posted December 2, 2009 Share Posted December 2, 2009 Hello, Coming from C# I have a difficult time comprehending events in C++. All I found on Google was twenty different snippets of code with little explanation, which is why I am asking here. My situation is as follows: I have a State class which is the base class for GameState and PauseState. The state is responsible for handling input from the player. Managing the states is the StateManager. The StateManager is capable of switching between states. Currently, the constructor of State requires a reference to the StateManager so it can call the SetState method in it. I find this a horrid solution and wish to implement it so that StateManager subscribes to a StateChanged event in the State class which can then be fired when the escape key is pressed ala C#. How would I go about implementing such a system in C++? Thanks! Quote Link to comment Share on other sites More sharing options...
Pixel Perfect Posted December 2, 2009 Share Posted December 2, 2009 Take a look at my blog as I detailed a subscribe and notify system in there for my Player and User Input class. The Player class registers events with the User Input class and gets notified when they occur. It's the 'For those who might be interested' post in September 1 Quote Intel Core i5 2.66 GHz, Asus P7P55D, 8Gb DDR3 RAM, GTX460 1Gb DDR5, Windows 7 (x64), LE Editor, GMax, 3DWS, UU3D Pro, Texture Maker Pro, Shader Map Pro. Development language: C/C++ Link to comment Share on other sites More sharing options...
Laurens Posted December 2, 2009 Author Share Posted December 2, 2009 Thanks Pixel, that was extremely helpful Cheers! Quote Link to comment Share on other sites More sharing options...
Rick Posted December 2, 2009 Share Posted December 2, 2009 I also have an event system that I've used a few years. The perk that this system has over most, not to take anything away from Pixel's system, is that it doesn't require your class methods to be static. You can run into scope issues with class data and static methods. I'll try to find it. The implementation is kind of complex, but the usage is very simple. Here would be an example of the usage: class Button { private: public: Event1<int> OnClick; }; class MyForm { private: void cmdExit_Click(int i) {} public: Button* cmdExit; MyForm() { cmdExit = new Button(); cmdExit->OnClick.Bind(this, MyForm::cmdExit_Click); } }; MyForm frm; // this will end up calling MyForm::cmdExit_Click() // the cool thing is that I have it setup so you can have a calling chain. I can any number // of different methods to the cmdExit->OnClick, and when I .Raise() the event all the // functions tied to it will be called frm.cmdExit->OnClick.Raise(5) One of the cool things also is that your function that handles your event can also be private to the class to prevent anyone from calling the event function directly. Quote Link to comment Share on other sites More sharing options...
Pixel Perfect Posted December 2, 2009 Share Posted December 2, 2009 You're welcome Laurens. Sounds interesting Rick. I'd be interested in seeing the implementation of that if you can find it. I'm always up for integrating better solutions if I can find them. Quote Intel Core i5 2.66 GHz, Asus P7P55D, 8Gb DDR3 RAM, GTX460 1Gb DDR5, Windows 7 (x64), LE Editor, GMax, 3DWS, UU3D Pro, Texture Maker Pro, Shader Map Pro. Development language: C/C++ Link to comment Share on other sites More sharing options...
Laurens Posted December 3, 2009 Author Share Posted December 3, 2009 That seems really interesting Rick, the usage almost feels like C# I would love to see the implementation if you can dig it up. Cheers! Quote Link to comment Share on other sites More sharing options...
Rick Posted December 4, 2009 Share Posted December 4, 2009 That seems really interesting Rick, the usage almost feels like C# I would love to see the implementation if you can dig it up. Cheers! Here it is in all it's glory. It's very much like how C# handles events. If you are familiar with C# you know that all events take 2 parameters. If you aren't familiar with templates your head might explode following the code below. You will note that below is for an event that takes 2 parameters to the functions that you link to it and returns a void. Because this uses templates those parameter types are defined by you like so Event2<int, string> myEvent; You can just put this in a header file, and include that header file wherever you want to use this and you're good to go. #include <list> using namespace std; template<class P, class Q> class TFunctor2 { public: virtual void Call(P var1, Q var2)=0; }; template <class TClass, class param1, class param2> class TSpecificFunctor2 : public TFunctor2<param1, param2> { private: void (TClass::*fpt)(param1, param2); TClass* pt2Object; public: TSpecificFunctor2(TClass* _pt2Object, void(TClass::*_fpt)(param1, param2)) { pt2Object = _pt2Object; fpt=_fpt; } virtual void Call(param1 var1, param2 var2) { (*pt2Object.*fpt)(var1, var2); } }; template<class T1, class T2> class Event2 { public: list<TFunctor2<T1, T2>* > mCaller; template<class Target> Event2(Target* t, void (Target::*fnPtr)(T1, T2)) { mCaller.push_back(new TSpecificFunctor2<Target, T1, T2>(t,fnPtr)); } Event2(){} template<class Target> void Bind(Target* t, void (Target::*fnPtr)(T1, T2)) { mCaller.push_back(new TSpecificFunctor2<Target, T1, T2>(t,fnPtr)); } void Raise(T1 V1, T2 V2) { list<TFunctor2<T1, T2>*>::reverse_iterator iter; for (iter = mCaller.rbegin(); iter!= mCaller.rend(); iter++) { (*iter)->Call(V1, V2); } } void Clear() { mCaller.clear(); } }; I didn't create this code so I can't take credit for it. I learned it from another game programming library, but honestly I have never seen a better C++ event system than what this gives you. This is as close to how .NET handles events that you can get in C++. It's easy to use. I would highly recommend studying the code and actually understand how it's working because it's pretty powerful, but for the first few months I just used it and didn't care how it worked If you want to create event functions that have different signatures then you would copy the above code, and do some renaming and re-templating. For example if you wanted a function that took 3 variables you would change the function names to have a 3 at the end, and then add another template class type to the classes. I gave you 2 parameter signature because that's how .NET handles events. It passes in the calling object and the parameter structure. Quote Link to comment Share on other sites More sharing options...
Rick Posted December 4, 2009 Share Posted December 4, 2009 Here is a small example of how to use it. This assumes you took the above code and put it in a file named Event.h Widget.h #pragma once #include "Event.h" #include <string> using namespace std; class Widget { private: void Widget_onClick(Widget* w, string p); public: Widget(void); ~Widget(void); public: Event2<Widget*, string> onClick; }; Widget.cpp #include "Widget.h" Widget::Widget(void) { onClick.Bind(this, &Widget::Widget_onClick); } Widget::~Widget(void) { } void Widget::Widget_onClick(Widget *w, std::string p) { } mian.cpp #include "Widget.h" int main() { Widget w; w.onClick.Raise(&w, "hello"); // this will end up calling Widget::Widget_onClick which is a private function of Widget return 0; } 2 Quote Link to comment Share on other sites More sharing options...
Laurens Posted December 4, 2009 Author Share Posted December 4, 2009 That is working simply amazing, thanks a bunch Rick Quote Link to comment Share on other sites More sharing options...
Rick Posted December 4, 2009 Share Posted December 4, 2009 np. I'd love to see what you do with it. Quote Link to comment Share on other sites More sharing options...
Pixel Perfect Posted December 4, 2009 Share Posted December 4, 2009 Thanks from me too Rick ... much appreciated Quote Intel Core i5 2.66 GHz, Asus P7P55D, 8Gb DDR3 RAM, GTX460 1Gb DDR5, Windows 7 (x64), LE Editor, GMax, 3DWS, UU3D Pro, Texture Maker Pro, Shader Map Pro. Development language: C/C++ Link to comment Share on other sites More sharing options...
fallingbrickwork Posted December 4, 2009 Share Posted December 4, 2009 This thread has been a good read! many thanks guys! Regards, Matt. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.