Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/135.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何使函数以任意函数指针作为参数?_C++_Pointers_Function Pointers - Fatal编程技术网

C++ 如何使函数以任意函数指针作为参数?

C++ 如何使函数以任意函数指针作为参数?,c++,pointers,function-pointers,C++,Pointers,Function Pointers,我正在努力做到以下几点,我甚至不确定这是否可能 我想要一个函数,它接受一个任意函数指针,将其传递给另一个函数(我知道这是一种代码味道,好的软件工程实践不是我现在要讨论的) 换句话说,我正在寻找的是: void method1(arbitraty pointer p) { method2(p); } 我不确定是否有方法声明任意函数指针(返回值保证为空,但参数在数量和类型上都是任意的)有些人可能认为这过于工程化,但您可以尝试以下方法: method2(BaseFunctor* myfunc

我正在努力做到以下几点,我甚至不确定这是否可能

我想要一个函数,它接受一个任意函数指针,将其传递给另一个函数(我知道这是一种代码味道,好的软件工程实践不是我现在要讨论的)

换句话说,我正在寻找的是:

void method1(arbitraty pointer p)
{
    method2(p);
}

我不确定是否有方法声明任意函数指针(返回值保证为空,但参数在数量和类型上都是任意的)

有些人可能认为这过于工程化,但您可以尝试以下方法:

method2(BaseFunctor* myfunctor) {
   if (myfunctor) 
      (*myfucntor)();
} 
创建您感兴趣的每个回调的枚举:

enum GlfwCallback {
    KeyCallback,
    FramebufferSizeCallback,
    // etc.
};
然后创建一个类型族,将这些类型中的每一个与相应的函数指针类型相关联。通过创建一个模板结构并反复对其进行专门化,可以做到这一点:

template<GflwCallback callback>
struct GlfwCallbackType {};

template<>
struct GlfwCallbackType<KeyCallback> {
    using CallbackType = GLFWkeyfun;
    // or
    using CallbackType = void(*)(GLFWwindow *, int, int, int, int);
};

template<>
struct GlfwCallbackType<FramebufferSizeCallback> {
    using CallbackType =  GLFWframebuffersizefun;
};

// etc.
模板
结构GlfwCallbackType{};
样板
结构GlfwCallbackType{
使用CallbackType=GLFWkeyfun;
//或
使用CallbackType=void(*)(GLFWwindow*,int,int,int,int);
};
样板
结构GlfwCallbackType{
使用CallbackType=GLFWframebuffersizefun;
};
//等等。
然后你就可以写了

template<GlfwCallback callback>
void method1(GlfwCallbackType<callback>::CallbackType p) {
    // do something with p
    method2<callback>(p);
};
模板
void方法1(GlfwCallbackType::CallbackType p){
//用p做点什么
方法2(p);
};

另外,请注意,您可以根据应用程序的需要向“类型族”中添加其他类型,甚至静态函数和数据成员。

有些人可能认为这过于工程化,但您可以尝试以下操作:

method2(BaseFunctor* myfunctor) {
   if (myfunctor) 
      (*myfucntor)();
} 
创建您感兴趣的每个回调的枚举:

enum GlfwCallback {
    KeyCallback,
    FramebufferSizeCallback,
    // etc.
};
然后创建一个类型族,将这些类型中的每一个与相应的函数指针类型相关联。通过创建一个模板结构并反复对其进行专门化,可以做到这一点:

template<GflwCallback callback>
struct GlfwCallbackType {};

template<>
struct GlfwCallbackType<KeyCallback> {
    using CallbackType = GLFWkeyfun;
    // or
    using CallbackType = void(*)(GLFWwindow *, int, int, int, int);
};

template<>
struct GlfwCallbackType<FramebufferSizeCallback> {
    using CallbackType =  GLFWframebuffersizefun;
};

// etc.
模板
结构GlfwCallbackType{};
样板
结构GlfwCallbackType{
使用CallbackType=GLFWkeyfun;
//或
使用CallbackType=void(*)(GLFWwindow*,int,int,int,int);
};
样板
结构GlfwCallbackType{
使用CallbackType=GLFWframebuffersizefun;
};
//等等。
然后你就可以写了

template<GlfwCallback callback>
void method1(GlfwCallbackType<callback>::CallbackType p) {
    // do something with p
    method2<callback>(p);
};
模板
void方法1(GlfwCallbackType::CallbackType p){
//用p做点什么
方法2(p);
};

另外,请注意,您可以根据应用程序的需要向“类型族”中添加其他类型,甚至静态函数和数据成员。

一种可能的做法是使用functor,即为
操作符()定义重载的类。

由于函子是一个类,因此可以将参数设置为数据成员,并将要作为任意指针传递的函数的实现/调用移动到operator()方法中,在该方法中,您可以通过
this
指针访问所有参数

此外,您可以定义一个函子层次结构,每个函子都有专门的参数和实现,因此您可以修改method2的签名,如下所示:

method2(BaseFunctor* myfunctor) {
   if (myfunctor) 
      (*myfucntor)();
} 
并在调用上下文中设置正确类型的函子对象


还可以查看lambdas(c++11),它基本上是函数定义的快捷方式。

可以做您想做的事情,但以一种很好的、类型安全的方式,就是使用函数,即为
操作符()定义重载的类。

由于函子是一个类,因此可以将参数设置为数据成员,并将要作为任意指针传递的函数的实现/调用移动到operator()方法中,在该方法中,您可以通过
this
指针访问所有参数

此外,您可以定义一个函子层次结构,每个函子都有专门的参数和实现,因此您可以修改method2的签名,如下所示:

method2(BaseFunctor* myfunctor) {
   if (myfunctor) 
      (*myfucntor)();
} 
并在调用上下文中设置正确类型的函子对象


还可以查看lambdas(c++11),它基本上是函数定义的快捷方式。

仅当导出的类型是函数指针类型时,才使用template和SFINAE启用它:

template <typename T, std::enable_if_t<std::is_function<T>::value, int> = 0>
void method1(T* p)
{
    // ...
}
模板
无效方法1(T*p)
{
// ...
}

仅当导出的类型为函数指针类型时,才使用模板并使用SFINAE启用它:

template <typename T, std::enable_if_t<std::is_function<T>::value, int> = 0>
void method1(T* p)
{
    // ...
}
模板
无效方法1(T*p)
{
// ...
}

<代码>打开你的C++书籍,教你如何使用模板。模板是现代C++最先进的部分之一,因此,StasOffFuff.com上简短的一两段答案不足以解释这个主题。你需要自己学习这个主题,读一本好书。我想你可以传递一个空指针并强制转换它,但是如果你打算从method2内部调用函数,我肯定会抱怨代码气味-具有不同参数数的函数不能互换-它们对堆栈指针所做的更改会被烘焙到生成的代码中,因此,如果您将2参数函数指针强制转换为1参数函数指针并调用它,您将打碎堆栈。我喜欢上面评论中的“模板”答案,顺便说一句,你应该看看。也有可变的模板,也许这些会起作用。你打算在method2中用指针做什么?完整的问题是我正在尝试为GLFW窗口创建一个包装类,用于将来的项目。我试图通过这个方法来设置每个GLFW回调函数。到目前为止,我一直在滥用这样一个事实,即大多数GLW回调函数都有不同的签名,只是dup[/]每个回调函数的代码都是完整的,但很重要的问题是,你打算用方法2中的指针做什么?显示使用它的代码行。打开C++书到教你如何使用模板的章节。模板是现代C++最先进的部分之一,因此,短