【问题标题】:Build & execute a stack of void functions构建并执行一堆 void 函数
【发布时间】:2011-09-24 20:10:39
【问题描述】:

我正在尝试存储函数的向量(或堆栈)。这个想法是我有一系列功能可以在主窗口中添加和删除小部件。我使用计时器警报,每当警报被调用时,我都会调用函数堆栈顶部的函数。

所以我的函数将始终是 void 类型。我的问题/误解是如何删除 stl::stack 的 void 函数以及如何执行该函数?

class InstructionScreen
{

  std::stack <void*> instructionSteps;  // is this how I declare a stack of functions

  void runTimerEvent()
  {
      if ( !instructionSteps.empty() ) 
      {
          // call the function at the top of the stack
          // how do I call the function?
          (*instructionSteps.top()); // is that how?
          instructionSteps.pop();
      }
  }

  void step1()
  {
     // here I create some widgets & add them to the main window
  }

  void step2()
  {
     // delete widgets from window
     // create some different widgets & add them to the main window
  }

  void buildStack()
  {
     instructionSteps.push( (&step1()) ); // is this correct?
     instructionSteps.push( (&step2()) );  
  }

};

【问题讨论】:

    标签: c++ function stack


    【解决方案1】:

    静态函数指针的语法如下:

    void (*FuncPtr)();
    

    对于成员指针,您必须使用以下语法:

    void (class::*FuncPtr)();
    

    如果你的函数不要求函数是成员函数,那么它会干净很多。一旦你弄清楚你需要什么样的函数,最简单的方法就是像这样对这些函数进行 typedef:

    typedef void(*FuncPtrType)();
    typedef void(Class::*MemberFuncPtrType)();
    

    现在您可以简单地声明一个带有函数指针的堆栈,如下所示:

    std::stack <FuncPtrType> funcPtrStack;
    std::stack <MemberFuncPtrType> memberFuncPtrStack;
    

    要获得指向函数的指针,您只需使用“&”运算符,就像在 C++ 中获得指向任何其他数据类型的地址一样:

    FuncPtrType funcPtr = &staticFunc; // Somewhere "void staticFunc()" is defined
    MemberFuncPtrType memberFuncPtr = &Class::MemberFunc; // Somewhere void "Class::MemberFunc()" is defined
    

    要实际调用函数指针,您可以使用“*”运算符从指针中取回数据(就像 C++ 中的任何其他数据类型一样)。唯一棘手的是成员函数需要一个指向类的指针,这使得使用起来非常尴尬。这就是为什么我建议一开始就使用静态函数。无论如何,这里是语法:

    (*funcPtr)(); // I just called a function with a pointer!
    (this->*memberFuncPtr)(); // I just wrote some ugly code to call a member function
    

    展示了所有这些之后,下面的代码现在应该有意义了:

    std::stack <MemberFuncPtrType> memberFuncPtrStack; // Declaring the stack
    memberFuncPtrStack.push( &Class::MemberFunc ); // Pushing a function
    (ClassPtr->*memberFuncPtrStack.top())(); // Calling the function with ClassPtr
    

    【讨论】:

    • 你调用成员函数的代码不对,必须是(obj.*mem_fun_ptr)();.*是一个运算符。即使是指针也更好,只需使用 -&gt;* 运算符:(obj_ptr-&gt;*mem_fun_ptr)();
    【解决方案2】:

    提示:使用 Boost.Function,会容易很多。它不仅会存储具有精确类型的函数,还可以存储任何其他可以以相同方式调用的函数。

    std::stack<boost::function<void()> instructionSteps;
    int foo() { return 42; }
    instructionSteps.push(foo); // Close enough - return value will be discarded.
    

    【讨论】:

      【解决方案3】:

      声明一个typedef 并创建一个vector/stack

      typedef void (*funcptr)();
      std::stack<funcptr> instructionSteps;
      

      用法:

      instructionSteps.push(&step1);
      instructionSteps.push(&step2);  
      

      demo here。 执行:

      instructionSteps.top()();
      

      【讨论】:

        【解决方案4】:

        我会typedef函数指针让你的生活更轻松:

        typedef void(*voidFunctionPointer)(); // Assuming here that the functions take no arguments.
        
        std::stack<voidFunctionPointer> instructionSteps; // This is very different from <void*>.  
                                                          // The latter is merely a stack of void pointers.
        

        调用顶层函数的一种方式是这样的:

        voidFunctionPointer functionToCall = instructionSteps.top();
        functionToCall();
        

        如果你想在没有额外声明的情况下这样做,我认为这应该可行。如果我错了,请纠正我。

        instructionSteps.top()();
        

        要构建堆栈,只需使用不带任何尾括号的函数名。

        instructionSteps.push(step1);
        instructionSteps.push(step2);
        // ...
        

        【讨论】:

          【解决方案5】:

          void* 指针不是合法的函数指针。应该是void (*)(),可以用typedef void (*stack_function)()做得更好。

          std::stack<stack_function> instructionSteps;
          

          要向其中推入某些内容,您不会调用函数(就像使用 step1() 一样),当然也不会像使用 &amp;step1() 那样获取返回地址(无论如何都是无效的) ,你只需要单独使用函数名:

          instructionSteps.push(step1); // the & can be omitted for free functions
          instructionSteps.push(&step2); // equivalent to the above, only a different function
          

          要从栈顶调用东西,你实际上需要一个调用:

          (*instructionSteps.top())();
          //    you missed that -- ^^
          

          取消引用也可以省略,因为这里解释的时间太长,搜索 SO。 :)

          instructionSteps.top()();
          

          【讨论】:

          • @Maxpm:嗯,要获得指向成员函数的指针,您需要&amp;:&amp;MyClass::my_func。我可以看到你来自哪里,不过,措辞有点模棱两可。改变了。
          【解决方案6】:
          typedef void (*fptr)();
          class InstructionScreen
          {
          
            std::stack <fptr> instructionSteps; 
          

          【讨论】:

            猜你喜欢
            • 2012-09-18
            • 2020-01-17
            • 1970-01-01
            • 2014-09-17
            • 1970-01-01
            • 2018-09-22
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多