可调用对象
2022-11-11 本文已影响0人
arkliu
可调用对象分类
- 函数指针
void fun(int age, string name) {
cout << "age :"<<age <<" name:"<<name<<endl;
}
using funptr = void(*)(int,string);
- 具有operator()成员函数的类对象(防函数)
class AA{
public:
void operator()(string name) {
cout << "AA name:" << name << endl;
}
};
int main() {
AA a;
a("hello world");
return 0;
}
- lambda函数
auto func1 = [](int age, string name) {
std::cout << age <<" "<< name<<std::endl;
};
func1(22, "张三");
- 一个可被转换为函数指针的类对象
void fun(int age, string name) {
cout << "age :"<<age <<" name:"<<name<<endl;
}
using funptr = void(*)(int,string);
class AA{
public:
void operator()(string name) {
cout << "AA name:" << name << endl;
}
operator funptr() {
return printAA; // printAA这里必须是static类型
}
static void printAA(int age, string name) {
cout << "age :"<<age <<" name:"<<name<<endl;
}
};
int main() {
AA a;
a("hello world");
AA aa;
aa(33, "张三");
return 0;
}
image.png
- 类函数成员指针或类成员指针
#include<iostream>
#include<string>
#include<typeinfo>
#include <map>
#include <vector>
using namespace std;
void fun(int age, string name) {
cout << "age :"<<age <<" name:"<<name<<endl;
}
using funptr = void(*)(int,string);
class AA{
public:
int m_age;
string m_name;
void operator()(string name) {
cout << "AA name:" << name << endl;
}
// 将类对象转换为函数
operator funptr() {
return printAA; // printAA这里必须是static类型
}
static void printAA(int age, string name) {
cout << "printAA age :"<<age <<" name:"<<name<<endl;
}
void fun1(int age ,string name) {
cout << "fun1 age :"<<age <<" name:"<<name<<endl;
}
};
int main() {
// 类的函数指针
funptr ptr1 = AA::printAA;
using Fptr = void(AA::*)(int age, string name);
Fptr ptr2 = &AA::fun1;
AA aa;
(aa.*ptr2)(33, "李四"); // fun1 age :33 name:李四
// 类的成员指针
using FMemberPtr = int AA::*;
FMemberPtr ptr3 = &AA::m_age;
aa.m_age = 45;
cout << "aa.m_age = "<<aa.m_age<< endl; // aa.m_age = 45
return 0;
}
可调用对象包装器
std::function是可调用对象的包装器,它是一个类模板,可以容纳除了类成员(函数)指针之外的所有可调用对象,
std::function 必须要包含一个叫做 functional 的头文件
语法如下:
#include <functional>
std::function<返回值类型(参数列表)> name= 可调用对象;
#include<iostream>
#include<string>
#include<typeinfo>
#include <map>
#include <vector>
#include<functional>
using namespace std;
void fun(int age, string name) {
cout << "age :"<<age <<" name:"<<name<<endl;
}
using funptr = void(*)(int,string);
class AA{
public:
int m_age;
string m_name;
void operator()(string name) {
cout << "AA name:" << name << endl;
}
operator funptr() {
return printAA; // printAA这里必须是static类型
}
static void printAA(int age, string name) {
cout << "printAA age :"<<age <<" name:"<<name<<endl;
}
void fun1(int age ,string name) {
cout << "fun1 age :"<<age <<" name:"<<name<<endl;
}
};
int main() {
// 1. 包装普通函数
function<void(int,string)>pfun1 = fun;
// 2. 包装类的静态函数
function<void(int,string)>pfun2 = AA::printAA;
// 3. 包装仿函数
AA a1;
function<void(string)>pfun3 = a1;
// 包装转换为函数指针的对象
AA a2;
function<void(int,string)>pfun4 = a2;
// 包装lambda
auto lamFun = [](int age, string name) {
std::cout << age <<" "<< name<<std::endl;
};
function<void(int,string)> pfun5 = lamFun;
// 包装类的成员函数
function<void(AA&, int,string)> pfun6 = &AA::fun1;
//调用
pfun1(11, "aaa");
pfun2(22, "bbbb");
pfun3("cccc");
pfun4(33, "dddddd");
pfun5(43, "sdfsdf");
pfun6(a1, 66, "mmmm");
return 0;
}
image.png
std::bind
std::bind用来将可调用对象与其参数一起进行绑定。绑定后的结果可以使用std::function进行保存
std::bind语法
// 绑定非类成员函数/变量
auto f = std::bind(可调用对象地址, 绑定的参数);
// 绑定类成员函/变量
auto f = std::bind(类函数/成员地址, 类实例对象地址, 绑定的参数);
bind基本用法
void fun(int age, string name) {
cout << "age :"<<age <<" name:"<<name<<endl;
}
int main() {
function<void(int,string)> fun_bind1 = bind(fun, placeholders::_1, placeholders::_2);
fun_bind1(12, "王五");
// 使用bind绑定参数顺序
function<void(string,int)> fun_bind2 = bind(fun, placeholders::_2, placeholders::_1);
fun_bind2("王五", 12);
// 使用bind提前绑定参数, 默认bind绑定参数是值传递,如果要传递引用使用std::ref()处理
int age = 18;
// function<void(string)> fun_bind3 = bind(fun, age, placeholders::_1);
function<void(string)> fun_bind3 = bind(fun, std::ref(age), placeholders::_1);
age = 30;
fun_bind3("牛牛牛牛牛");
// function包装函数参数比bind绑定的函数参数个数多的情况
function<void(int, string, int)> fun_bind4 = bind(fun, placeholders::_1, placeholders::_2);
fun_bind4(22, "uuuu", 0);
return 0;
}
image.png
bind绑定
int main() {
// 1. 包装普通函数
auto pfun1 = bind(fun, placeholders::_1, placeholders::_2);
// 2. 包装类的静态函数
auto pfun2 = bind(AA::printAA, placeholders::_1, placeholders::_2);
// 3. 包装仿函数
AA a1;
auto pfun3 = bind(a1, placeholders::_1);
// 包装转换为函数指针的对象
AA a2;
function<void(int,string)>pfun4 = bind(a2, placeholders::_1, placeholders::_2);
// 包装lambda
auto lamFun = [](int age, string name) {
std::cout << age <<" "<< name<<std::endl;
};
function<void(int,string)> pfun5 = bind(lamFun, placeholders::_1, placeholders::_2);
// 包装类的成员函数, 使用bind直接绑定对象
function<void(int,string)> pfun6 = bind(&AA::fun1, &a1, placeholders::_1, placeholders::_2);
//调用
pfun1(11, "aaa");
pfun2(22, "bbbb");
pfun3("cccc");
pfun4(33, "dddddd");
pfun5(43, "sdfsdf");
pfun6(66, "mmmm"); // 上面使用bind直接绑定对象,这里使用时候,就不用传递对象了
return 0;
}
image.png