Stack of class member functions but the class isn't known yet
I have something a little tricky to explain so I'll try my best. I have an InstructionScreen class that displays arrows & blocks of text that explain what each buttons does & etc. So in InstructionScreen I have a stack of member functions each of those functions will create some arrows & text to explain what a different button does.
The InstructionScreen will be subclassed into MenuInstructScreen, OptionsInstructScreen & etc. and in these classes I will create custom functions that will create arrows & text to explain their screens buttons.
The problem is declaring this stack in InstructionScreen because it will contain functions that are part of their subclass. I am thinking I can do this, but I use templates right?
So the problem in a nutshell is how do I declare a stack that will contain member functions of a class that doesn't exist yet?
The problem is a lot easier to understand & see if you look at this simple example:
typedef class InstructionScreen;
typedef class MenuInstructScreen;
templ开发者_高级运维ate <typename FooClass>
typedef void (FooClass::*MemberFuncPtr)(); // will be typedef void (MenuInstructScreen::*MemberFuncPtr)();
class InstructionScreen
{
public:
InstructionScreen() {}
void runInstructions()
{
while ( !instructionStep.empty() )
{
(this->*instructionStep.top())();
instructionStep.pop();
}
}
protected:
stack <MemberFuncPtr> instructionStep;
};
class MenuInstructScreen : public InstructionScreen
{
public:
MenuInstructScreen()
{
// Set instruction schedule
instructionStep.push( &MenuInstructScreen::step2() );
instructionStep.push( &MenuInstructScreen::step1() );
}
void step1()
{
// create some widgets that point to buttons & widgets that contain text instructions
}
void step2()
{
// create some widgets that point to buttons & widgets that contain text instructions
}
private:
};
class OptionsInstructScreen : public InstructionScreen
{
public:
OptionsInstructScreen()
{
// Set instruction schedule
instructionStep.push( &OptionsInstructScreen::step2() );
instructionStep.push( &OptionsInstructScreen::step1() );
}
void step1()
{
// create some widgets that point to buttons & widgets that contain text instructions
}
void step2()
{
// create some widgets that point to buttons & widgets that contain text instructions
}
private:
};
C++ doesn't allow templated typedefs, but C++11 supports this via Template Aliases. If you don't have C++11 support in your compiler, you could achieve the same by using a functor such as Boost.Function
.
typedef boost::function<void()> Func;
Since your typedef is for member functions that take no arguments, you could use the aboce to define a functor that returns void and accepts no arguments. Although it wouldn't be restricted to members of a specific class. You would push items onto your stack in derived classes using something like:
stack.push(boost::bind(&MenuInstructScreen::step2, this));
stack.push(boost::bind(&MenuInstructScreen::step1, this));
Your original example would now look something like this...
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <stack>
class InstructionScreen
{
public:
void runInstructions()
{
while (!instructionStep.empty())
{
boost::function<void()> func = instructionStep.top();
instructionStep.pop();
func();
}
}
protected:
std::stack<boost::function<void()> > instructionStep;
};
class MenuInstructScreen : public InstructionScreen
{
public:
MenuInstructScreen()
{
instructionStep.push(boost::bind(&MenuInstructScreen::step2, this));
instructionStep.push(boost::bind(&MenuInstructScreen::step1, this));
}
void step1()
{
//
}
void step2()
{
//
}
};
class OptionsInstructScreen : public InstructionScreen
{
public:
OptionsInstructScreen()
{
instructionStep.push(boost::bind(&OptionsInstructScreen::step2, this));
instructionStep.push(boost::bind(&OptionsInstructScreen::step1, this));
}
void step1()
{
//
}
void step2()
{
//
}
private:
};
int main() { }
There are no "template typedef"s in C++. In C++0x you can use template aliases, but support for that is limited at the moment.
Why not simply add a virtual function to your base class:
virtual void steps() { };
Then let each derived class implement it:
void steps() { step1(); step2(); }
Then you can store pointers-to-base-class in your stack and just call ->steps()
.
精彩评论