Jump to content
xisto Community

FurryHead

Members
  • Content Count

    10
  • Joined

  • Last visited

About FurryHead

  • Rank
    Newbie [Level 1]

Contact Methods

  • Website URL
    http://furryhead.co.cc

Profile Information

  • Gender
    Male
  1. Sorry, I wrote the class declaration wrong. The data members should be "protected:" and not defaulted to private, so that it will be subclass-able. Change the top of the "class Event" declaration as follows: template<class Data> class Event { protected: // protected so that subclasses can inherit the data typedef void (*fptr)(Data); std::vector<fptr> listeners; // the rest of code... Sorry!
  2. Hey everyone, I'm going to teach you how to make a simple event handler in C++. If you happen to be familiar with C#'s event handler system, this is going to mimic that. I got the idea from a tutorial on how to make this same class in Python, but I couldn't find anything comparable to it in C++. Plus, it might be useful to someone... Anyway, on to the code. I would recommend basic knowledge of generic classes, operator overloading, and the concept of function pointers. If you don't happen to know these, I will offer a really basic explanation along the way. Note: All of this will be done from within Code::Blocks, it should be relatively easy to follow along with any other environment though. So, to start with we will create two files - One header for the event handler class, one for the test program. Name them 'event.h' and 'main.cpp'. I would use a separate file for the event handler declarations and definitions, but with generics you can't do that. Unlike with a non-generic class, it will not give you linkage errors if you put the definitions in the header because of the way it compiles. Now, in order to keep track of all the listeners to add we will be using a vector of function pointers. More on this later. So we will add the following skeleton code into event.h: #include <vector>#include <algorithm> // For the remove listener function so we can use std::remove_iftemplate <class Data> class Event { typedef void (*fptr)(Data); typename std::vector<fptr> listeners; public: // nothing yet!}; Alright, now let's go through this line by line (after the includes) template <class Data> class Event { This line says that this is a generic class, and to define "Data" as whatever type is passed to us when the user creates a instance of this class. So, if we made a instance of this class as "Event<string> myEventHandler;" it would define Data as type string. If you want more detailed information about generics, see a C++ book or a tutorial or google it. typedef void (*fptr)(Data); This (basically) defines the type "void (*)(Data)" to fptr, so when we use "fptr myPtr;" we are declaring (a lot easier) a pointer to a function returning void taking a parameter of type "Data". typename std::vector<fptr> listeners; Creates a vector of function pointers. The typename keyword is sometimes needed to tell the compiler that 'Data' in the fptr typedef is a template name, not a object name - big difference, especially since g++ will spew unreadable errors about it. Well, we have a basic skeleton now. Now we will add the operators! Add these two functions right after the public: line and before the last }; Event& operator+=(fptr func) { return add(func); } Event& operator-=(fptr func) { return sub(func); } void operator()(Data& eventData) { changed(eventData); } Well, each of those are pretty much the same - they delegate to other functions. Read any tutorial on operator overloading for information on the first two... But I must explain the third one a little. The third one is really neat, it's called a "Functor" - basically, look at the following code: Event handler; // assuming we have finished the classhandler.add(function_name); // These two lineshandler += function_name; // have the exact same effect (the same applies to sub and -=)//here's the neat functorhandler("Some new data");handler.changed("Some new data");The last two lines accomplish the exact same thing! I suppose this is why the docs call functors "Functions on steroids" See google for more functor information. Anyway, we now need to define the other 3 functions - add, sub, and changed. We'll start with changed(): void changed(Data& eventData) { for (typename std::vector<fptr>::iterator iter = listeners.begin(); iter != listeners.end(); ++iter) { (*iter)(eventData); }}Well, assuming you know at least the basics of C++ you will know what the first line does. I'll go over the other two lines, though: for (typename std::vector<fptr>::iterator iter = listeners.begin(); iter != listeners.end(); ++iter) { If you've ever iterated over a vector, it's the same except for the typename keyword. It tells the compiler that Data is a template name not a object name. But wait, where did we say Data in this line? Well, we didn't. We said it in the typedef for fptr; Therefore it implies that it's here as well. Try compiling it without the typename, and good luck trying to understand the errors. (*iter)(eventData); This is the interesting part. To call a function through it's pointer, you can either use "fptr func_ptr; func_ptr =...; func_ptr();" as if it's a normal function, but the more common use is "(*func_ptr)()" because it explicitly tells the reader that it's calling a pointer to a function. Since we are using a iterator, that adds another level of misdirection - Technically, we could also use "(**iter)(eventData)" because one * de-references the iter pointer to the original function pointer, then the second * de-references it to the function itself. In short, iter is now a pointer to a pointer to a function, and the function can be called as "(**iter)(eventData)" OR (*iter)(eventData)". Read up on function pointers for more details. Now for the other two functions: Event& add(fptr func) { for (typename std::vector<fptr>::iterator iter = listeners.begin(); iter != listeners.end(); ++iter) { if (*iter == func) // we must dereference the pointer-to-pointer-to-function to get the pointer-to-function so that we can compare it // Case was true, the function has already been added so we return and don't add it again return *this; } // Ok, func has not yet been added (or added then removed) so we can add it listeners.push_back(func); return *this;}// helper function for std::remove_ifbool evt_equal(fptr func1, fptr func2) { return (func1 == func2);}Event& sub(fptr func) { // This line removes all occurrences of func in the listeners list, if any. listeners.erase(std::remove_if(listeners.begin(), listeners.end(), evt_equal), listeners.end()); return *this;}Well, most of it is commented and explains itself, but I will talk about returning the "this" pointer for a moment. The special keyword "this" is a pointer to the class instance that you're working from. When you say "return this;" it is returning a pointer - which is not good, as operators should return a reference to the object so that it is assignable to a non-pointer variable. So we de-reference the this pointer, thus returning the Event object in a way that is convenient to assign. Now, all the code put together in event.h is as follows: #include <vector>#include <algorithm>template<class Data> class Event { typedef void (*fptr)(Data); std::vector<fptr> listeners; public: void changed(Data& eventData) { for (typename std::vector<fptr>::iterator iter = listeners.begin(); iter != listeners.end(); ++iter) { (*iter)(eventData); } } Event& add(fptr func) { for (typename std::vector<fptr>::iterator iter = listeners.begin(); iter != listeners.end(); ++iter) { if (*iter == func) return *this; } listeners.push_back(func); return *this; } bool evt_equal(fptr func1, fptr func2) { return (func1 == func2); } Event& sub(fptr func) { listeners.erase(std::remove_if(listeners.begin(), listeners.end(), evt_equal), listeners.end()); return *this; } // operators Event& operator+=(fptr func) { return add(func); } Event& operator-=(fptr func) { return sub(func); } void operator()(Data& eventData) { changed(eventData); }};Looking good, eh? Well, now we can test it out!!! Here's the code for main.cpp, the comments will explain it: #include <string>#include <iostream>#include "event.h"using namespace std;void onEvent(string data) { cout << "Handler function called with: " << data << endl;}void onEvent2(string data) { cout << "Handler function number 2 called with: " << data << endl;}int main() { Event<string> handler; // Create an instance of Event, passing the string type as "Data" in the class handler.add(onEvent); // Pass the onEvent function to the Event class, telling it to notify the // function when something changes. also same as handler += onEvent; string msg = "My handler works!"; // make a message handler.changed(msg); // tell the event class that something changed, including the data - // update all the listener functions! also same as handler(msg); handler += onEvent2; // same as handler.add(onEvent2); msg += " (revisited!)"; // add new data handler(msg); // same as handler.changed(msg);}Now just compile it and have fun!!! One thing I want to comment about functors and function pointers is that they are interchangeable. If you define a class with a functor, you can use it as if it were a function pointer! See functor docs for more information. Any questions just post, I'll try to monitor this tutorial.
  3. I know this is a mildly old topic (3 months) but I just had to comment.I had no idea that you qualify one "myCENT" as 1.00! I thought 0.01 myCENTs == one myCENT, but from 8ennett's post it appears as though 1.00 == one myCENT. This was a very interesting read, and you guys ought to make it more clear that 1.00 myCENTs equal one myCENT, not 0.01 - that was confusing.So I guess when I have 7.77 myCENTs, I only really have the equivalent of 7 3/4 cents! I thought I had 7 3/4 *dollars*! LOL
  4. Well, Xarex, it can't be my computer because I was using another video card (Cirrus something, IIRC) and it worked fine. I have no other computers, other than a laptop, so I can't test the nVidia in another computer.I'm personally guessing that it's a memory module that has gotten corrupted, but I can't be sure - I am an idiot when it comes to hardware.On a side note, anyone know how to fix a IDE HDD that (I think) has gotten fried? AFAIK, nothing happened to it but it's no longer being recognized by the motherboard.
  5. Eeeeek! So apparently it's not repairable? Great, just what I needed - To be stuck with 800x600x16 resolution for ages.Thanks for the info, though. At least I know I have to start saving up for a new computer now, then. haha.
  6. Hey everyone, just sharing this really neat tool. A few months back, my laptop had a virus in it's HAL.DLL that kept giving me a BSOD about 10 minutes after each reboot. On another PC, I searched the internet for help - and up popped this neat program. NirSoft's BlueScreenView Spent a week trying to fix the repeating BSOD, and once I found this I fixed the error / removed the virus (by replacing my hal.dll with one from the CD) and back up and running within a half hour. About 25 minutes of that was rebooting/copying the dll. They also have applications for Vista/7 to view application crash logs, never tried it though. Best wishes to all of you!
  7. Nice specs guys. They don't even compare to mine, though:Desktop: Gateway PerformanceManufactured in about 2000640MB RAM750MHz Intel Pentium 3 Processor1.5GB Hard drive (Forgotten the brand)nVidia GeForce 256 video cardZip drive (Logo says Zip 100)Floppy drive (1.44mb)DVD-R (Not rewritable)Made for Win98 xDUses Lucid Puppy Linux 5.2 as OSLaptop: Toshiba Tecra8000 (broken LCD screen)Manufactured about 1998300MHz Intel Pentium 2 processor 12GB Hard driveNeoMagic MagichGraph256AV video cardCD-RExternal floppy driveMade for Win98Quad-boots Windows 2000 Pro, Puppy Linux 4.2.1, TinyCoreLinux 3.x, Slackware 13.1Told ya, yours don't even compare to mine LOL
  8. Hey everyone. (Sorry, mistakenly added 'AV' in the card description - I got that confused with my laptop's card, ignore it)I have a old desktop computer manufactured about 11 years ago, and it came with a nVidia GeForce 256 graphics card installed. (Not built-in; it came as a PCI card pre-installed)Now, for the past few years this card has worked perfectly fine. Until recently.Recently, my screen has abruptly started adding weird-colored lines across the screen, then promptly freezing my entire computer - keyboard, mouse, screen, all not working - and I have to power off/reboot using the power button.I ended up changing out the card with a ever older one that can't display anything higher than 800x600x16 resolution - which quickly got on my nerves.I've since put the nVidia card back in, and so far it's working fine - except for two times it's distorted the screen's color, then returned to normal.This has only happened about a year after I got linux, but I have no way of checking the card with a windows computer (the hard drive on my PC is too small).What could be causing this? I've checked the fan on the card, it's a bit dusty (after blowing compressed air at it) but it moves freely. Is there any way to fix this before it completely goes out (and I have to deal with 800x600x16 for the rest of this computer's life)?Thanks in advance!
  9. Hey everyone. I've been looking for a while, and on everyone else's posts it has a little line under their avatar, "myCENTs: xx.xx" - I do not see mine, and I do not see anywhere in my controls that show it either. (Also checked on Xisto - Support.com)I have signed up for an account on Xisto obviously, and a account on Xisto - Support.com with the same E-mail address. Must I do something to link them?I know I must be missing it somewhere, but I cannot find it. Can someone please tell me where it is? Thank you!
  10. I have been programming for about 3 years. I started originally when I was playing this neat MMORPG called RuneScape. I got tired of it, and discovered there was such a thing as private servers (user developed, user maintained). So, I started playing those. Eventually, I got tired of those too. I then said to myself, "Why am I playing on servers that are created by individuals? I am an individual, ** I ** can make one!" So, that started me off programming in Java. I didn't even know what a boolean was! Eventually I stopped dealing with the game programming, and decided to learn actual software development. After I quit programming the game servers, I started off in C# - then proceeded to jump from language to language trying to find one that suited me best. I later settled down with Python, and now I'm pretty good with that. After that, I decided to expand my horizons - and moved from the gentle learning curve of Python to the steep curve (in my opinion) of C++. I also have a litte experience in Perl, C, SmallBasic, more than a little Java, PHP, tiny weeny bit of JavaScript, bash scripting, and VB.NET. P.S.: easy_peasy - check out http://www.w3schools.com/php/php_intro.asp - I used them frequently when I was doing a bit of PHP, they're pretty good. I don't know anything about MySQL, however.
  11. I switched to linux because my hard drive got fried, and I had to use a tiny 1.5GB hard drive. Since, I've gotten more disk space (primarily by using my REALLY old laptop as a storage server) but even if I could switch to windows, I wouldn't.I first used Puppy Linux 4.3.1, booting from a USB drive (thank god that computer had supported USB-booting natively), and eventually installed it into my hard drive. Shortly after that came the fatal hard-drive-failure.I am still a avid puppy linux user, now running 5.2 - Ubuntu binary compatible \o/ - though if I had the choice, I'd be running debian lenny minimal install.Just my 2 cents.
  12. Aaah. I was wondering how they tied together. Thankfully I did just that Sorry I took so long to respond; I switched to Slax linux (under 200mb, with KDE!) and have been reconfiguring/reinstalling everything since... (pain, but worth it) One other question: Can I run long-term scripts on the SSH account? It's not going to use much bandwidth (or CPU); All it'd be doing is receiving connections and sending back a version number (an auto-updater app; client connects to server, server tells client to update if server version > client version) Thanks! P.S.: I should be more active now that I've got most of my OS set back up. Still need to set up Code::Blocks, though
  13. Hey everyone! I'm glad to have found Xisto, my old host (free) kept giving me warnings about resource usage going too high... I was using the WordPress wp-admin!!Anyway, about me: I'm a freelance software developer, I know Python, and am decent in Java, know a bit of PHP (just enough to tweak WordPress), and plan to learn C/C++ pretty soon. I like video gaming, writing games, software development, Linux, and good beta testers You'll probably see me most active in the software development forums, that's generally where my haven is. (that, and sitting at a linux terminal programming)The main reason I need a web host is for my website. I plan to create a website (or blog) to distribute my miscellaneous utilities I create. Also, I chose Xisto because you provide SSH access. <-- That will be a huge + for me, as I hate FTP. SSH is so much easier to manage things I have a question about your myCENTS program though, how does it tie with my account with Xisto - Support.com ? Thanks, and great service!
×
×
  • Create New...

Important Information

Terms of Use | Privacy Policy | Guidelines | We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.