【几种可调动对象,Function和bind;线程的调动方式举例】

news/2024/12/2 19:36:20/

1.可调动对象的调动方式

方法 1、函数指针调动
方法2 、类类型的括号的重载 调动可调动对象

#include<iostream>
#include<functional>
using namespace std;
struct Foo
{void operator()(int x){cout<<"Foo operator "<<x<<endl;}
};
struct Bar
{using Pfun =void (*) (int);Pfun成为一个类型static void func(int x){cout<<"Bar func"<<x<<endl;}operator Pfun()const{return &Bar::func;}
};
struct Test
{
public:int x_;Test(int x):x_(x){}
public:void funb(){cout<<" Test funb"<<x_<<" ";}int func(int x){x_= x;cout<<"Test func"<<x<<" ";}
};
int add(int x,int y)
{return x+y;
}
int main()
{int x=10;int *p = &x;方法调动1:通过函数指针void (*fp)(int) = Bar::func; fp(x);方法调动2:通过对象重载Foo foo;  foo(x);方法调动2:重载实现调动Bar bar;return 0;
}

打印结果:

Bar func10
Foo operator 10


方法3、function

struct Test
{
public:int x_;Test(int x):x_(x){}
public:void funb(){cout<<" Test funb"<<x_<<" ";}int func(int x){x_= x;cout<<"Test func"<<x<<" ";return x;}
};
int add(int x,int y)
{return x+y;
}
int main()
{std::function<int(int,int)>pfuna = add;auto val = pfuna(1,2);int x=10;Test test(10);  std::function<void(Test&)>pfunb =&Test::funb;pfunb(test);std::function<int(Test&,int )>pfunc = &Test::func;auto val1 = pfunc(test,100);有返回值,需要有值去接收cout<<val1<<endl;return 0;
}

打印结果:

Test funb10 Test func100 100

注意:<int(Test&,int )>尖括号中传入的是类型!


一个回调函数的例子:

/*function 一个回调函数的例子*/
class Test
{std::function<void()> callback;
public:Test(const std::function <void()>&f):callback(f){}void notify(){callback();}};class Foo
{
public:void operator()(void){cout<<__FUNCTION__<<endl;cout<<__TIME__<<endl;}
};
int main()
{Foo foo;Test test(foo); 通过foo对象去激活foo中的仿函数 !test.notify();return  0;
}

可调动对象之--------
lamda表达式


2 .BIND与FUNCTION 示例:

/bind/
//作用1:将可调用对象与其参数一起绑定成一个仿函数
//作用2:将多元(参数个数为n,n>1) 可调用对象转成一元或(n-1)元,即只绑定部分参数

#include<iostream>
#include<functional>
using namespace std;
class Test
{
public:int val;Test(int x =0):val(x){}void output(int a,int b){cout<<"a ="<<a<<"  b = "<<b<<"  val = "<<val<<endl;}};
void output(int a,int b)
{cout<<"a ="<<a<<"  b = "<<b<<endl;
}
int main()
{   function<void(int ,int)>Function = output;auto pfun = std::bind(Function,10,20); pfun();pfun(1,2); //此时的传入的参数并不起作用,因为绑定时已经给了固定的参数;auto pfuna = std::bind(Function,20); //error 格式中必须给两个参数auto pfunb = std::bind(Function,std::placeholders::_1,20);//第一个参数位给出占位符,//那么pfun(1,2)的第一个位置就被1占了;pfunb(1,2);Test test(10);auto pfunc = std::bind(&Test::output,test,std::placeholders::_1,placeholders::_2);//pfun;//没用调动可调动对象pfunc(1,2);****************************************************************bind直接执行可调动对象:*括号内给值-> bind直接执行可调动对象*std::bind(&Test::output,test,std::placeholders::_1,placeholders::_2)(100,200); *****************************************************************function 加bind调动类对象成员方法*Test test1(10);std::function<void(Test&,int,int)>Function1 = &Test::output;std::bind(Function1,test1,placeholders::_1,placeholders::_2)(200,300);*****************************************************************注意占位符和提取符的说法:*std::function<void(Test&,int,int)>Function2 = &Test::output;//std::bind(Function2,test1,placeholders::_1,placeholders::_3)(200,300);//errorstd::bind(Function2,test1,placeholders::_1,placeholders::_3)(100,200,300);//ok,第三个占位符可以提取到第三个参数return  0;}

lamda表达式:

int main()
{   int x= 10,z=20;// auto val = [](int a)->int {//     return a+1;// };//cout<<val(1);// auto val = [=]() -> int{//     return x+10;// };// cout<<val(); //无参也要写括号  //reuslt::20auto val = [&]() ->int {x += 1000;return x;};cout<<"val = "<<val()<<endl;  //必须执行完VAL()后x的值才发生变化。cout<<"x = "<<x<<endl;/*无返回值的测试*/[&]() ->void {x += 1000;};cout<<"val = "<<val()<<endl;  cout<<"x = "<<x<<endl;cout<<"val = "<<val()<<endl;cout<<"x = "<<x<<endl;//带形参的测试:auto num = [x,&z](int y)->int {return x+(z++);};cout<<"num = "<<num(1)<<endl;cout<<z<<endl;//只引用形式捕获z,其他为隐式的以值捕获auto num1 = [=,&z](int y)->int{return x+(z++);};cout<<"num1 = "<<num1(1)<<endl;cout<<z<<endl;//只以值捕获z,其他为隐式的以引用捕获auto num2 = [&,z](int y)->int{cout<<"lamda"<<x<<endl;return (x++)+z;};cout<<"num2 = "<<num2(1)<<endl;cout<<"x"<<x<<endl;return 0;
}

在这里插入图片描述


线程的几种执行方式

1.thread的使用

    void funa(int x){cout<<"funa"<<endl;}void funb(int *p){cout<<"funb"<<endl;}  void func(int &x){cout<<"func"<<endl;x+=10;}
int main()
{   int x=10;int *p =&x;thread tha(funa,1);thread thb(funb,p);//thread thd(func,x); //error 函数无法以引用接收thread thc(func,std::ref(x)); //oktha.join();thb.join();thc.join();//thd.join();cout<<x<<endl;return 0;}

结果:

funa
funb
func
20

/利用using 定义函数指针/

void fun(int x,int y)
{   cout<<"nihao:fun"<<std::endl;
}using PFUN = void (*)(int , int);PFUN funt = fun; //okstd::thread thp(funt,2,2);//ok

3.线程调动类成员方法

typedef void (*pfun)();
using PFUN = void (*)(void);
class mythread
{
public:mythread(int val):val_(val){}int val_;
public:void fun_thread(int val){cout<<val_<<endl;cout<<val<<endl;}};
int main()
{mythread my1;std::thread thc(&mythread::fun_thread,&my1,100);thc.join();return 0;
}

4./线程函数是仿函数的例子/

/*线程函数是仿函数的例子*/
class Test
{
public:void operator()(int x,int y){cout<<"add"<<x+y<<endl;}void add(int x,int y){cout<<"add 普通成员函数"<<x+y<<endl;}
};
int main()
{std::thread tha(Test{},1,2); //函数重载直接调动类的成员仿函数Test test;std::thread thb(&Test::add,&test,1,2); //调动成员函数thb.join();tha.join();return 0;
}

5./强转的例子/

class Test1
{
public:
int val = 190 ;
using PFUN = void (*)(int , int);
public:
static void add(int a,int b)
{int c=a+b;cout<<"add c"<<c<<endl;
}
operator PFUN()const
{return &add;
}
operator int()const
{return val;
}
};
int main()
{Test1 test1;int num =test1; //会调动重载的强转函数 operator int()test1(12,23); //result::add 35 .其实是下面的语句://test.operator Test::PFUN()(12,23);return 0;
}

test1(12,23); 调动过程:
test1后面的括号代表调动其重载函数,12,23为add的参数匹配,最后调动ADD函数。


lamda:

int main()
{/*lamda*/std::thread thc([&](int x_) -> void {x += x_; //这里x要用就必须被捕获,注意不能被值捕获(这里值被修改)},100);std::thread thc([=]()->void {printf("lamda \n");});thc.join();cout<<num<<endl;// 110return 0;
}

http://www.ppmy.cn/news/6715.html

相关文章

【VUE3】保姆级基础讲解(三)非父子组件通讯,$refs,动态组件,keep-alive,Composition API

目录 非父子组件通讯 全局事件总线mitt库 组件的生命周期 $refs 动态组件 keep-alive 异步打包 v-model绑定组件 Composition API 定义响应式数据 readonly toRefs与toRef computed $ref 生命周期钩子 provide和inject watch侦听 watchEffect script setup语法…

[JavaEE] 线程与进程的区别详解

专栏简介: JavaEE从入门到进阶 题目来源: leetcode,牛客,剑指offer. 创作目标: 记录学习JavaEE学习历程 希望在提升自己的同时,帮助他人,,与大家一起共同进步,互相成长. 学历代表过去,能力代表现在,学习能力代表未来! 目录 认识线程(Thread) 1. 线程是什么? 2. 为什么要有…

C#项目实战——【实例】企业人事管理系统(一):1、系统分析;2、系统设计;3、系统运行环境;

学习《C#从入门到精通》&#xff0c;边学边练记录实现过程。 1、系统分析 1.1、需求分析 基于其他企业人事管理软件的不足&#xff0c;要求能够制作一个可以方便、快捷地对职工信息进行添加、修改、删除的操作&#xff0c;并且可以在数据库中存储相应职工的照片。为了能够更…

【C++初阶】list的模拟实现

文章目录list的介绍list的模拟实现成员变量Member functionsconstructordestructoroperatorIterators正向迭代器反向迭代器beginendrbeginrendModifierspush_frontpop_frontpush_backpop_backinserteraseclear完整版代码list.hreverse_iterator.htest.cpplist的介绍 list是STL…

力扣:两数之和

原题链接&#xff1a;https://leetcode.cn/problems/two-sum/description/ 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&…

numpy数组,numpy索引,numpy中nan和常用方法

一&#xff1a;【numpy数组】 1.1为什么要学习numpy 1.快速 2.方便 3.科学计算的基础库 1.2什么是numpy 一个python中做科学计算的基础库&#xff0c;重在数值计算&#xff0c;也是大部分python科学计算库的基础库&#xff0c;多用于在大型&#xff0c;多维数组上执行数组运…

如何定制化Spring Boot Starter,这次我终于学会了

文章目录什么是Spring Boot Starter实现步骤启动器自动配置包总结自定义Starter的实现逻辑Spring Boot Starter官网描述&#xff1a;Spring Boot Starter官方介绍 什么是Spring Boot Starter Starters可以理解为启动器&#xff0c;它包含了一系列可以集成到应用里面的依赖包&…

shell脚本四剑客之awk详解

文章目录awk的介绍awk能够干什么awk的格式工作原理&#xff1a;记录和域内建变量的用法1. FS2. OFS3.RS4. ORS5. NF6. NRBEGIN 和END语句块常见案例1. 使用NR行号提取ip2. 打印UID小于10的账号名称和UID信息3. 数学运算4. AWK打印硬盘设备名称&#xff0c;默认以空格为分割&…