西安网站建设sxyun微信企业号网站开发软件
web/
2025/9/26 11:18:14/
文章来源:
西安网站建设sxyun,微信企业号网站开发软件,网站建设手机版模板,搜索引擎优化规则在C中存在“可调用对象”这么一个概念。准确来说#xff0c;可调用对象有如下几种定义#xff1a;
是一个函数指针#xff1a;
int print(int a, double b)
{cout a b endl;return 0;
}
// 定义函数指针
int (*func)(int, double) print…在C中存在“可调用对象”这么一个概念。准确来说可调用对象有如下几种定义
是一个函数指针
int print(int a, double b)
{cout a b endl;return 0;
}
// 定义函数指针
int (*func)(int, double) print;是一个具有operator()成员函数的类对象仿函数
#include iostream
#include string
#include vector
using namespace std;struct Test
{// ()操作符重载void operator()(string msg){cout msg: msg endl;}
};int main(void)
{Test t;t(我是要成为海贼王的男人!!!); // 仿函数return 0;
}是一个可被转换为函数指针的类对象
#include iostream
#include string
#include vector
using namespace std;using func_ptr void(*)(int, string);
struct Test
{static void print(int a, string b){cout name: b , age: a endl;}// 将类对象转换为函数指针operator func_ptr(){return print;}
};int main(void)
{Test t;// 对象转换为函数指针, 并调用t(19, Monkey D. Luffy);return 0;
}是一个类成员函数指针或者类成员指针 #include iostream
#include string
#include vector
using namespace std;struct Test
{void print(int a, string b){cout name: b , age: a endl;}int m_num;
};int main(void)
{// 定义类成员函数指针指向类成员函数void (Test::*func_ptr)(int, string) Test::print;// 类成员指针指向类成员变量int Test::*obj_ptr Test::m_num;Test t;// 通过类成员函数指针调用类成员函数(t.*func_ptr)(19, Monkey D. Luffy);// 通过类成员指针初始化类成员变量t.*obj_ptr 1;cout number is: t.m_num endl;return 0;
}关于应该注意到的一些细节都在注释里面了
#includeiostream
using namespace std;
/*1.是一个函数指针2.是一个具有operator()成员函数的类对象仿函数3.是一个可被转换为函数指针的类对象4.是一个类成员函数指针或者类成员指针
*///普通函数
void print(int num, string name)
{cout id num name name \n;
}using funcptr void(*)(int, string);
//类
class Test
{
public:// 重载void operator()(string msg){cout 仿函数 msg \n;}// 将类对象转化为函数指针operator funcptr()// 后面的这个()不需要写任何参数{// 不能返回hello虽然hello的参数也是int和string// 但是hello在未示例化之前是不存在的world是属于类的return world;// 虽然在定义的时候没有返回值但是在函数体里面必须要返回实际的函数地址}void hello(int a, string s){cout number a name s \n;}static void world(int a, string s){cout number a name s \n;}int m_id 520;string m_name luffy;
};int main()
{Test t;t(我是要成为海贼王的男人);// 重载被执行Test tt;tt(19, luffy);// 类的函数指针funcptr f Test::world;// 可以让普通的函数指针指向类中的静态函数不能指向非静态函数// 给函数指针加上作用域就可以指向类中的非静态函数了using fptr void(Test::*)(int, string);fptr f1 Test::hello;// 可调用对象// 类的成员指针(变量)using ptr1 int Test::*;// 属于Test类中的指针ptr1 pt Test::m_id;// 可调用对象Test ttt;(ttt.*f1)(20, ace);// 前面加()的原因是*的优先级低于右侧的参数列表ttt.*pt 100;cout m_id ttt.m_id \n;return 0;
}上述程序的输出结果为 C11通过提供std::function 和 std::bind统一了可调用对象的各种操作。
std::function是可调用对象的包装器。它是一个类模板可以容纳除了类成员函数指针之外的所有可调用对象。通过指定它的模板参数它可以用统一的方式处理函数、函数对象、函数指针并允许保存和延迟执行它们。
std::function必须要包含一个叫做functional的头文件可调用对象包装器使用语法如下:
#include functional
std::function返回值类型(参数类型列表) diy_name 可调用对象; 接下来演示可调用对象包装器的基本使用方法
#includeiostream
#includefunctional
using namespace std;
/*1.是一个函数指针2.是一个具有operator()成员函数的类对象仿函数3.是一个可被转换为函数指针的类对象4.是一个类成员函数指针或者类成员指针
*///普通函数
void print(int num, string name)
{cout id num name name \n;
}using funcptr void(*)(int, string);
//类
class Test
{
public:// 重载void operator()(string msg){cout 仿函数 msg \n;}// 将类对象转化为函数指针operator funcptr()// 后面的这个()不需要写任何参数{// 不能返回hello虽然hello的参数也是int和string// 但是hello在未示例化之前是不存在的world是属于类的return world;// 虽然在定义的时候没有返回值但是在函数体里面必须要返回实际的函数地址}void hello(int a, string s){cout number a name s \n;}static void world(int a, string s){cout number a name s \n;}int m_id 520;string m_name luffy;
};int main()
{
#if 0Test t;t(我是要成为海贼王的男人);// 重载被执行Test tt;tt(19, luffy);// 类的函数指针funcptr f Test::world;// 可以让普通的函数指针指向类中的静态函数不能指向非静态函数// 给函数指针加上作用域就可以指向类中的非静态函数了using fptr void(Test::*)(int, string);fptr f1 Test::hello;// 可调用对象// 类的成员指针(变量)using ptr1 int Test::*;// 属于Test类中的指针ptr1 pt Test::m_id;// 可调用对象Test ttt;(ttt.*f1)(20, ace);// 前面加()的原因是*的优先级低于右侧的参数列表ttt.*pt 100;cout m_id ttt.m_id \n;
#endif// 打包// C中的function主要用于包装可调用的实体// 也就是函数。这些可调用的实体包括普通函数、函数指针、成员函数、静态函数、// lambda表达式和函数对象。所以你可以认为std::function包装的都是函数。// 1.普通包装函数// 只是对print函数进行打包f1是不会被调用的若想f1中的函数体执行还需要额外的再次调用functionvoid(int, string) f1 print;// 2.包装类的静态函数functionvoid(int, string) f2 Test::world;// 3.包装仿函数Test ta;functionvoid(string) f3 ta;// 4.包装转化为函数指针的对象Test tb;functionvoid(int, string) f4 tb;// 调用f1(1, ace);f2(2, sabo);f3(luffy);f4(3, robin);return 0;
}代码运行结果 通过测试代码可以得到结论std::function可以将可调用对象进行包装得到一个统一的格式包装完成得到的对象相当于一个函数指针和函数指针的使用方式相同通过包装器对象就可以完成对包装的函数的调用了。
function作为回调函数使用 因为回调函数本身就是通过函数指针实现的使用对象包装器可以取代函数指针的作用。
回调函数的基本概念和作用
在C中回调函数Callback Function是指一种通过函数指针或函数对象传递给其他函数的函数。这种机制允许你在某个事件发生或条件满足时通过调用指定的函数来实现定制的操作。
回调函数通常用于实现异步操作、事件处理、以及在框架或库中注册自定义行为。
回调函数的示例代码
#include iostream// 定义回调函数的原型
typedef void (*CallbackFunction)(int);// 接受回调函数作为参数的函数
void performOperation(int data, CallbackFunction callback) {// 执行某些操作std::cout Performing operation with data: data std::endl;// 调用回调函数callback(data);
}// 示例回调函数
void callbackFunction(int data) {std::cout Callback function called with data: data std::endl;
}int main() {// 使用回调函数调用 performOperationperformOperation(42, callbackFunction);return 0;
}输出结果为
Performing operation with data: 42
Callback function called with data: 42解释一下输出结果
1. performOperation 函数被调用传递了参数 42然后输出了一条包含该数据的信息。
2. 在 performOperation 函数内部回调函数 callbackFunction 被调用将参数 42 传递给它。
3. callbackFunction 函数被执行输出了一条包含传递给它的数据的信息。
因此整体输出结果包括了两行信息一行是在执行 performOperation 时的信息另一行是在执行回调函数 callbackFunction 时的信息。这演示了回调函数的基本概念其中一个函数在特定事件或条件发生时调用另一个函数。
接下来是关于function作为回调函数的使用的代码
#includeiostream
#includefunctional
using namespace std;
/*1.是一个函数指针2.是一个具有operator()成员函数的类对象仿函数3.是一个可被转换为函数指针的类对象4.是一个类成员函数指针或者类成员指针
*///普通函数
void print(int num, string name)
{cout id num name name \n;
}using funcptr void(*)(int, string);
//类
class Test
{
public:// 重载void operator()(string msg){cout 仿函数 msg \n;}// 将类对象转化为函数指针operator funcptr()// 后面的这个()不需要写任何参数{// 不能返回hello虽然hello的参数也是int和string// 但是hello在未示例化之前是不存在的world是属于类的return world;// 虽然在定义的时候没有返回值但是在函数体里面必须要返回实际的函数地址}void hello(int a, string s){cout number a name s \n;}static void world(int a, string s){cout number a name s \n;}int m_id 520;string m_name luffy;
};class A
{
public:// 构造函数参数是一个包装器对象// 这就意味着可以给这个构造函数传递四种类型的可调用对象// 传进来的可调用对象并没有直接使用而是存在callback中// 在实例化对象后调用notify函数相当于一个回调操作A(const functionvoid(int, string) f) : callback(f){}void notify(int id, string name){callback(id, name);// 调用通过构造函数得到函数指针}private:functionvoid(int, string) callback;
};int main()
{
#if 0Test t;t(我是要成为海贼王的男人);// 重载被执行Test tt;tt(19, luffy);// 类的函数指针funcptr f Test::world;// 可以让普通的函数指针指向类中的静态函数不能指向非静态函数// 给函数指针加上作用域就可以指向类中的非静态函数了using fptr void(Test::*)(int, string);fptr f1 Test::hello;// 可调用对象// 类的成员指针(变量)using ptr1 int Test::*;// 属于Test类中的指针ptr1 pt Test::m_id;// 可调用对象Test ttt;(ttt.*f1)(20, ace);// 前面加()的原因是*的优先级低于右侧的参数列表ttt.*pt 100;cout m_id ttt.m_id \n;
#endif// 打包// C中的function主要用于包装可调用的实体// 也就是函数。这些可调用的实体包括普通函数、函数指针、成员函数、静态函数、// lambda表达式和函数对象。所以你可以认为std::function包装的都是函数。// 1.普通包装函数// 只是对print函数进行打包f1是不会被调用的若想f1中的函数体执行还需要额外的再次调用functionvoid(int, string) f1 print;// 2.包装类的静态函数functionvoid(int, string) f2 Test::world;// 3.包装仿函数Test ta;functionvoid(string) f3 ta;// 4.包装转化为函数指针的对象Test tb;functionvoid(int, string) f4 tb;// 调用f1(1, ace);f2(2, sabo);f3(luffy);f4(3, robin);A aa(print);aa.notify(1, ace);A ab(Test::world);ab.notify(2, sabo);// 包装仿函数也可以传参这里不能是因为参数类型不一致// 这里包装仿函数的参数为(int, string)A ac(tb);ac.notify(3, luffy);return 0;
}
上述代码的运行结果为 通过上面的例子可以看出使用对象包装器std::function可以非常方便的将仿函数转换为一个函数指针通过进行函数指针的传递在其他函数的合适的位置就可以调用这个包装好的仿函数了。
另外使用std::function作为函数的传入参数可以将定义方式不相同的可调用对象进行统一的传递这样大大增加了程序的灵活性。
本文参考可调用对象包装器、绑定器 | 爱编程的大丙 (subingwen.cn)
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/82168.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!