c++ - 是否可以保存带有参数的函数指针供以后使用?

标签 c++ function class c++11 function-pointers

昨天,我尝试编写一个基本的渲染器,其中渲染器控制何时将数据加载到着色器中,而可渲染对象对正在使用的着色器一无所知。作为一个顽固的人(而且 sleep 不足),我花了几个小时试图将函数指针发送到渲染器,保存,然后在适当的时间运行。直到后来我才意识到我要构建的是一个消息系统。不过,这让我想知道,是否有可能保存带有参数的函数指针,以便稍后在 c++ 中运行。

我最初的想法是这样的:

// set up libraries and variables
Renderer renderer();
renderable obj();
mat4 viewMatrix();
// renderer returns and object id
int objID = renderer.loadObj(obj)

int main()
{
  //do stuff
  while(running)
  {
    //do stuff
    renderer.pushInstruction(//some instruction);
    renderer.render();
  }
}

// functionPtr.h
#include <functional>

class storableFunction
{
  public:
  virtual ~storableFunction = 0;
  virtual void call() = 0;
};

template<class type>
class functionPtr : public storableFunction
{
  std::function<type> func;
public:
  functionPtr(std::function<type> func)
    : func(func) {}
  void call() { func(); }
};

//renderer.h
struct  modelObj
{
  // model data and attached shader obj
  std::queue<storableFunction> instruction;
}

class renderer
{
  std::map<int, modelObj> models;
public:
    // renderer functions
    void pushInputDataInstruction(int id, //function, arg1, arg2);
    // this was overloaded because I did not know what type the second argument  would be
    // pushInputDataInstruction implementation in .cpp
    {
      models[id].instruction.push(functionPtr(std::bind(//method with args)))
    }
  void render();
};

//implantation in .cpp
{
  for(// all models)
  //bind all data
  applyInstructions(id);
  // this would call all the instructrions using functionptr.call() in the queue and clear the queue
  draw();
  // unbind all data
}

我意识到 boost 可能支持某种类似的功能,但我想避免使用 boost

这样的事情是否可能,一般设计会是什么样子,它甚至会被用来做什么,因为消息总线是这样的事情的更成熟的设计模式?

最佳答案

std::bind 是一种方法,但如果您可以访问 C++ 11 及更高版本,则可能需要考虑改用 lambda。 Scott Meyer 建议在 Effective Modern C++ 中使用它们而不是 std::bind(在大多数情况下)。

lambda 包含三个部分:

  • [] 部分,标识要捕获的值或引用,
  • () 部分,它标识稍后将在调用 lambda 时提供的参数。
  • {} 部分,标识如何处理捕获的值和参数

简单的例子:

#include <iostream>

void printValue(int x) {
    std::cout << x << std::endl;
}

int main(int argc, char * argv[]) {
    int x = 23;

    // [x] means 'capture x's value, keep it for later'
    // (int y) means 'I'll provide y when I invoke the lambda'
    auto storedFunction = [x](int y){return printValue(x + y);};

    x = 15;

    // Now we invoke the lamda, with y = 2
    // Result: 25 (23 + 2), even if x was changed after the lambda was created
    storedFunction(2); 
    return 0;
}

如果要捕获对 x 的引用,请使用 [&x]。在上面的示例中,结果将是 17(即 15 + 2)。如果您确实使用引用,请注意不要让 xstoredFunction 之前超出范围,因为它会成为对垃圾数据的悬空引用。

现在大多数编译器都支持 C++ 11,但您可能需要在项目设置中明确添加支持:

  • Visual Studio:项目属性/C++/语言/C++ 语言标准
  • gcc: --std=c++11(或 14,或 17...)
  • CMake 还允许您设置标准:set (CMAKE_CXX_STANDARD 11)

关于c++ - 是否可以保存带有参数的函数指针供以后使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52063007/

相关文章:

c++ - cocos2dx C++ 循环遍历 cocos2d::Vector

c++ - 如何检测 .h 文件是否包含 .cpp 文件中未定义的函数?

c++ - 读取一个数字,使用简单的方法将其显示在屏幕上(C++)

php - 从 PHP 中的父类访问具有冲突名称的子属性

python - 传递给 Python 中所有实例方法的预处理参数

c++ - 返回的通用 lambda 的参数据称会影响自由函数的参数

Javascript 嵌套函数 - 有什么区别?

javascript - 如何在游戏重新启动时阻止 Javascript 多次调用函数

javascript - JS中如何检查无效参数?

android - 简单的自定义类扩展 View