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);//error
std::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::20
auto 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)); //ok
tha.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; //ok
std::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;// 110
return 0;
}