Стек функций-членов класса, но класс еще не известен - PullRequest
1 голос
/ 03 июля 2011

Мне нужно кое-что объяснить, поэтому я буду стараться изо всех сил.У меня есть класс InstructionScreen, который отображает стрелки и блоки текста, которые объясняют, что делает каждая кнопка и т. Д. Поэтому в InstructionScreen у меня есть набор функций-членов, каждая из которых создаст несколько стрелок и текста, чтобы объяснить, что делает другая кнопка.

Экран InstructionScreen будет разделен на MenuInstructScreen, OptionsInstructScreen и т. Д., И в этих классах я создам пользовательские функции, которые будут создавать стрелки и текст для объяснения кнопок их экранов.

Проблема заключается в объявлении этого стека в InstructionScreen, потому что он будет содержать функции, которые являются частью их подкласса.Я думаю, что могу сделать это, но я использую шаблоны правильно?

Итак, проблема в двух словах: как мне объявить стек, который будет содержать функции-члены класса, который не 't еще существует?

Проблема намного легче понять и увидеть, если вы посмотрите на этот простой пример:

typedef class InstructionScreen;
typedef class MenuInstructScreen;
template <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:

};

Ответы [ 2 ]

1 голос
/ 03 июля 2011

C ++ не допускает шаблонные определения типов, но C ++ 11 поддерживает это через Псевдонимы шаблона .Если у вас нет поддержки C ++ 11 в вашем компиляторе, вы можете добиться того же, используя функтор, такой как Boost.Function.

typedef boost::function<void()> Func;

Поскольку ваш typedef предназначен дляФункции-члены, которые не принимают аргументов, вы можете использовать aboce для определения функтора, который возвращает void и не принимает аргументов.Хотя это не будет ограничено членами определенного класса.Вы бы помещали элементы в свой стек в производных классах, используя что-то вроде:

stack.push(boost::bind(&MenuInstructScreen::step2, this));
stack.push(boost::bind(&MenuInstructScreen::step1, 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() { } 
0 голосов
/ 03 июля 2011

В C ++ нет "шаблонных типов определения". В C ++ 0x вы можете использовать псевдонимы шаблонов , но в настоящее время его поддержка ограничена.

Почему бы просто не добавить виртуальную функцию в базовый класс:

virtual void steps() { };

Тогда пусть каждый производный класс реализует его:

void steps() { step1(); step2(); }

Затем вы можете хранить указатели на базовый класс в вашем стеке и просто вызывать ->steps().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...