开发者

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().

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜