可调用对象和可调用对象的包装器

文章介绍了C++中的可调用对象,包括函数指针、仿函数对象和将类对象转化为函数指针的用法,并详细讲解了std::function作为可调用对象的包装器,如何统一处理不同类型的函数、函数对象和延迟执行。此外,还展示了std::function在实现回调函数中的应用。
摘要由CSDN通过智能技术生成

1、可调用对象

可调用对象是C++11引入的概念,可以像函数调用方式的触发调用的对象就是可调用对象。如下是可调用对象的几种定义:

1.1、函数指针

函数指针的可调用对象的测试代码:

#include<iostream>
#include<string>

int myTest(int a, std::string b)
{
	std::cout << "a = " << a << " b = " << b << std::endl;
	return 0;
}

//定义函数指针---->C++98
typedef int(*func)(int, std::string);

//使用using定义函数指针--->C++11
using func1 = int(*)(int, std::string);

int main()
{
	func f= myTest;
	func1 f1 = myTest;
	f(10, "Naruto");
	f1(20, "Sakura");

	return 0;
}

测试代码的结果:
在这里插入图片描述

1.2、仿函数对象

仿函数的意思就是类似于函数的意义,一般是指写入了operator()运算符方法的类就是一个仿函数,如下是一个具有operator()成员函数的类对象:

#include<iostream>
#include<string>

class Test
{
public:
	Test() = default;
	void operator()(std::string msg)
	{
		std::cout << "msg:" << msg << std::endl;
	}
};

int main()
{
	Test t;
	t("I want to be Naruto");
	return 0;
}

测试代码的结果:
在这里插入图片描述

1.3、类对象转化为函数指针

可调用对象的最后一个常见的类型为类对象转化为函数指针,测试代码如下:

#include<iostream>
#include<string>

//使用using定义函数指针
using funcPtr = void(*)(int, std::string);

class Test
{
public:
	Test() = default;
	static void printMsg(int a, std::string b)
	{
		std::cout << "I am " << b << " is " << a << " years old";
	}
	//类对象转化为函数指针
	operator funcPtr()
	{
		return printMsg;
	}
};

int main()
{
	Test t;
	t(20, "Naruto");
	return 0;
}

测试代码的结果:
在这里插入图片描述

注意:上面例举的都是常用的可调用对象,不是只有3种可调用对象!!!

2、可调用对象的包装器

std::function是可调用对象的包装器。它是一个类模板,可以容纳除了类成员(函数)指针之外的所有可调用对象。通过指定它的模板参数,它可以用统一的方式处理函数、函数对象、函数指针,并允许保存和延迟执行它们

2.1、std::function的使用方法

在使用std::function之前首先要包含它的头文件functional,它的语法如下:

//导入头文件
#include <functional>
//包装器的语法
std::function<返回值类型(参数类型列表)> diy_name = 可调用对象;

下面简单演示可调用对象的包装器的使用:

#include<iostream>
#include<functional>
#include<string>

void printMsg(int age, std::string name)
{
	std::cout << "I am " << name << " is " << age << " years old" << std::endl;
}

class Test1
{
public:
	Test1() = default;
	static int add(int a, int b)
	{
		std::cout << "a + b = " << a + b << std::endl;
		return a + b;
	}
};

class Test2
{
public:
	Test2() = default;
	int operator ()(int a, int b)
	{
		std::cout << "a * b =" << a * b << std::endl;
		return a * b;
	}
};


int main()
{
	//包装普通函数
	std::function<void(int, std::string)>f1 = printMsg;
	//包装类中的静态函数
	std::function<int(int, int)>f2 = Test1::add;
	//包装仿函数
	Test2 t2;
	std::function<int(int, int)>f3 = t2;

	//函数的调用
	f1(20, "Naruto");
	f2(2, 2);
	f3(5, 5);
	return 0;
}

测试代码的结果:
在这里插入图片描述

通过上面的代码可知,std::function可以对可调用对象进行包装,得到一个统一的格式,包装完成后得到的包装器对象相当于一个仿函数,向里面传入参数即可完成函数调用

2.2、作为回调函数

因为回调函数本身是通过函数指针实现,在C++11以后我们可以通过可调用对象的包装器取代函数指针,实现回调函数,测试代码如下:

#include<iostream>
#include<functional>
#include<string>

class Test1
{
public:
	//初始化包装器
	Test1(const std::function<void()>& f) : m_callBack(f)
	{

	}
	void doSomething()
	{
		m_callBack();
	}
private:
	std::function<void()>m_callBack;
};

class Test2
{
public:
	Test2() = default;
	void operator()()
	{
		std::cout << "hello World" << std::endl;
	}
};

int main()
{
	//通过构造函数获取包装器,执行回调函数
	Test2 t2;
	Test1 t1(t2);
	t1.doSomething();
	return 0;
}

测试代码的结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值