存储在类中的函数指针

Function pointer stored in class

本文关键字:函数 指针 存储      更新时间:2023-10-16

我希望能够在结构体或类中存储函数的指针,那么我可以在按下按钮时调用该函数吗? 这是我所拥有的:

struct INFO
{
std::function<int(int, int)> call_back;
};
class YO
{
public:
YO() {};
~YO() {};
int SUM(int A, int B) { return A + B; }
};
int main()
{
//std::function<int(int, int)> datFunc = SUM;
INFO info;
YO* yo = new YO();
info.call_back = yo->SUM;
//std::function<int(int, int)> func =;
std::cout << info.call_back(10, 10) << std::endl;
system("pause");
return 0;
}

我收到错误:

Error   C3867   'YO::SUM': non-standard syntax; use '&' to create a pointer to member   FunctionPointertest 
Error   C2679   binary '=': no operator found which takes a right-hand operand of type 'overloaded-function' (or there is no acceptable conversion) FunctionPointertest 

您还需要向函数调用提供主机对象的实例,在本例中为 YO。 std::function 支持这一点,在它可以执行的许多转换中,但随后原型变成了

std::function<int(YO*, int, int)> call_back;

当你调用它时:

info.call_back(&yo, 10, 10)

一些选项可以做你想做的事。使用 lambda 是最好的解决方案。

void func() {
INFO info;
YO yo;
YO* yo2 = new YO;
info.call_back = [&yo](int a, int b) {
return yo.SUM(a, b);
};
using namespace std::placeholders;
info.call_back = std::bind(&YO::SUM, std::ref(yo), _1, _2);
info.call_back = std::bind(&YO::SUM, yo2, _1, _2);
}

附言您通常不想在 c++ 中使用new

这里有一组VariadicTemplateClasses,如果你有可用的C++17,它们将使您能够轻松做到这一点。第一个类只是存储任何类型的std::function的通用版本!第二类通过member function存储第一类,并将registerfunction pointerfunction objectlambda。它还有另一个member function可以invoke它。我目前正在此示例中使用lambdas。我有两个lambdas,第一个st采用两种int类型将它们添加并返回一个int,如上面的问题所示。第 2需要两个std::strings将它们连接起来,然后将它们打印到屏幕上,但不返回任何值。甚至可以通过在驱动程序类中存储std::vector<Functor<>>来扩展它。register_callback会略有变化,将它们推入矢量,call_back您有选择。您可以一次性调用它们,也可以通过索引值搜索以调用特定的索引值,但我会将其作为练习留给您。

#include <string>
#include <iostream>
#include <functional>
template<typename RES_TYPE, typename... ARG_TYPES>
struct Functor {
std::function<RES_TYPE( ARG_TYPES... )> func_;
};
template<typename RES_TYPE, typename... ARG_TYPES>
class Driver {
private:
Functor<RES_TYPE, ARG_TYPES...> functor;
public:
Driver() = default;
~Driver() = default;
void register_callback( const Functor<RES_TYPE, ARG_TYPES...> &func ) {
functor = func;
}
RES_TYPE call_back( ARG_TYPES... args ) {
return functor.func_( std::forward<ARG_TYPES>(args)... );
}    
};    
int main() {
// Function Type: int ( int, int );
Functor<int, int, int> func;
auto lambda = []( int a, int b ) { return a + b; };
func.func_ = lambda;
Driver<int, int, int> driver;
driver.register_callback( func );
int a = 3;
int b = 5;
std::cout << driver.call_back( a, b ) << 'n';
std::cout << driver.call_back( 7, 5 ) << 'n';
// Function Type: void ( string, string );
Functor<void, std::string, std::string> func2;
auto lambda2 = []( std::string str1, std::string str2 ) {
str1 = str1 + " " + str2;
std::cout << str1 << 'n';
};
Driver <void, std::string, std::string> driver2;
func2.func_ = lambda2;
driver2.register_callback( func2 );
std::string str1 = "Hello";
std::string str2 = "World";
driver2.call_back( str1, str2 );
driver2.call_back( "Generic", "Programming" );
return 0;
}

输出为:

8
12
Hello World
Generic Programming

如果你注意到这里的代码;没有必要弄乱指针或动态内存。这一切都可以通过为我们使用std::function和类的默认dtors来解决。

我尽力设计得简单易读,同时使其尽可能便携和通用。我相信可以做出一些改进,但我认为这符合您的要求。