Original Post
HI,!
Check out the following code I had a problem with a few days ago:
I fixed the initial problem I had getting it to run which now allows me to turn my attention towards actually trying to work out what's going on. Basically the code is simulating what would happen if you had a button on a screen which played music when you clicked it. The author decided to use a class inheritance style function object. Quite crafty really, it means you can define one Button class and then define as many inherited varieties of the class Action as you like and Button will accept them all.
Great, but the code is not completed by the author and he's left some rather puzzling things in his wake. I'll start with the first things I'm puzzled by:
1)
2)
I do have more questions but that's enough for now! ANy insight anyone can offer would be most well received cheers! ;o)
Check out the following code I had a problem with a few days ago:
#include <iostream>#include <string>class Action{ public: virtual ~Action(void){} virtual void operator () (void) = 0; // both these must be implemented for virtual Action* clone(void) const = 0; // this class to work};class Button{ public: Button(const std::string& label) : label_(label), action_(0) {} void setAction(Action* newAction) { Action* temp = newAction->clone(); // this is the bit I'm puzzled by! delete action_; action_ = temp; } void onClick(void) const { if(action_){(*action_)();} // also this bit! } private: std::string label_; Action* action_;};class PlayMusic : public Action{ public: PlayMusic(const std::string& songfile) : song_(songfile) {} ~PlayMusic(void) { return; } void operator()(void) { std::cout << "PlayMusic operator overload running" << std::endl; } Action* clone(void) const { std::cout << "PlayMusic clone function running" << std::endl; return const_cast<PlayMusic*>(this); // I hacked this to get it to run!! ;o) } private: std::string song_;};int main(){ Button myButton("MyButton"); PlayMusic myPlayMusic("MyPlayMusic"); myButton.setAction(&myPlayMusic); return 1;}I fixed the initial problem I had getting it to run which now allows me to turn my attention towards actually trying to work out what's going on. Basically the code is simulating what would happen if you had a button on a screen which played music when you clicked it. The author decided to use a class inheritance style function object. Quite crafty really, it means you can define one Button class and then define as many inherited varieties of the class Action as you like and Button will accept them all.
Great, but the code is not completed by the author and he's left some rather puzzling things in his wake. I'll start with the first things I'm puzzled by:
1)
void setAction(Action* newAction) { Action* temp = newAction->clone(); // this is the bit I'm puzzled by! delete action_; action_ = temp; }The setAction function in Button is odd. Why does it call the clone function in newAction to get a pointer to an Action instead of just using the pointer passed to it in the argument? What the hell does the clone function do, and why would its returned pointer take preference over the argument?2)
void onClick(void) const { if(action_){(*action_)();} // also this bit! }A real puzzle. If I get this right, this function is checking to see if the action_ data member doesn't point to NULL and then dereferences the pointer presumably with a constructor call. Now that's ok if you're accessing the base class. But you can't access the base class. It has pure virtuals in it so is 'abstract' and is never meant to exist standalone. Given that all its inherited classes have a constructor call which take a string argument what exactly is going to happen when this function executes on the action_ data member when it's pointing to a derived class - in this example a class called PlayMusic (which takes a string as an argument)?I do have more questions but that's enough for now! ANy insight anyone can offer would be most well received cheers! ;o)