当前位置: 首页 > news >正文

C++语法|可调用对象与function类型

文章目录

  • 引入
  • function的使用
  • function类型的典型应用
  • function类型的原理
    • 实现
    • 代码优化
      • 可变参的函数对象

引入

还记得C语言中的函数指针数组吗?
我们通过函数指针数组实现一个,图书管理系统的界面:

#include <stdio.h>
void doShowAllBooks() {printf("查看所有书籍信息\n");
}
void doBorrow() {printf("借书\n");
}
void doBack() {printf("还书\n");
}
void doQueryBooks() {printf("查询书籍\n");
}
void doLoginOut() {printf("注销\n");
}
int main() {int choice = 0;void (*actionArray[5])() = {doShowAllBooks, doBorrow, doBack, doQueryBooks, doLoginOut};while (1) {printf("----------------\n");printf("1.查看所有书籍信息\n");printf("2.借书\n");printf("3.还书\n");printf("4.查询书籍\n");printf("5.注销\n");printf("----------------\n");printf("请选择: ");scanf("%d", &choice);if (choice < 1 || choice > 5) {printf("输入数字无效,重新选择\n");} else {// 调用相应的函数(*actionArray[choice - 1])();}}return 0;
}

我们通过函数指针数组集中保留了我们的函数,让巧用显得十分方便,那么在C++中,我们也有类似的实现。

function的使用

我觉得function简单一点来理解就是它能够保留可调用对象
function是一个模板,当我们创建这个模板的时候需要一些额外的信息,所谓的额外信息就是指该function类型能够表示的对象的调用形式:

function<int(int, int)>

表示我们生命里一个function类型,它可以接受两个int、返回一个int的可调用对象。

void hello1() {cout << "hello world!" << endl;
}void hello2(string str) {    //void (*pfunc) (string)用函数指针调用cout << str << endl;
}int sum(int a, int b) {return a + b;
}class Test {
public: //成员方法的调用必须依赖一个对象void (Test::*pfunc) (string)void hello(string str) {cout << str << endl; }
};int main () {//从function 的类模板定义处,用一个函数类型实例化functionfunction<void()> func1 = hello1; // func1(hello1)func1(); //func1.operator() ==> hello1()function<void(string)> func2 = hello2;func2("hello hello2"); //dunc2.operator(string str) ==> hello2(str)function<int(int, int)> func3 = sum;cout << func3(1, 1) << endl;//保留函数对象 operator()function<int(int, int)> func4 = [](int a, int b)->int {return a + b; };cout << func4(100, 200) << endl;//对类的成员方法也可以进行保留  hello有两个参数 一个是this指针一个是string strfunction<void(Test*, string str)> func5 = &Test::hello;Test t;//func5(&Test(), "call Test::hello"); 报错,至少clang g++不允许func5(&t, "Call Test::hello");return 0;
}

function类型的典型应用

通过定义map和function类型实现一个读书管理系统。

void doShowAllBooks() { cout << "查看所有书籍信息" << endl; }
void doBorrow() { cout << "借书" << endl; }
void doBack() { cout << "还书" << endl; }
void doQueryBooks() { cout << "查询书籍" << endl; }
void doLoginOut() { cout << "注销" << endl; }int main()
{int choice = 0;// 用C语言的函数指针其实也可以实现这个例子(采用数组来映射函数指针)// 但是他不能实现lambda表达式和函数对象map<int, function<void()>> actionMap;actionMap.insert({1, doShowAllBooks}); // insert(make_pair(xx, xx));actionMap.insert({2, doBorrow});actionMap.insert({3, doBack});actionMap.insert({4, doQueryBooks});actionMap.insert({5, doLoginOut});for (;;){cout << "----------------" << endl;cout << "1.查看所有书籍信息" << endl;cout << "2.借书" << endl;cout << "3.还书" << endl;cout << "4.查询书籍" << endl;cout << "5.注销" << endl;cout << "----------------" << endl;cout << "请选择: ";cin >> choice;auto it = actionMap.find(choice);if (it == actionMap.end()) {cout << "输入数字无效,重新选择" << endl;} else {it->second();}

function类型的原理

通过举例来说明,有如下例子,func1可以打印hello world!

void hello(string str) { cout << str << endl; }
int main () {function<void(string str)> func1(hello); // func1 = hello;func1("hello world");return 0
}

实现

通过分析我们可以知道function我们可以使用模板类来实现它,在这个模板类中,我们需要使用一个函数指针来指向hello函数。然后需要重载函数调用运算符。

  • 首先我们需要实现一个通用的模板类my_function,这个通用模板类不需要任何实现。仅仅让编译器找到匹配的模板类定义
//my_function<void(string)> func1(hello);
template<typename Fty>
class my_function { };
  • 实现特例化的模板类
template<typename R, typename A1>
//my_function<void(string)> func1(hello);
class my_function<R(A1)> {
public:using PFUNC = R (*) (A1);my_function(PFUNC pfunc) : _func(pfunc) {}R operator() (A1 arg) const {return _pfunc(arg); } //hello(arg)
private:PFUNC _pfunc;
}
  • 调用检验
int main() {my_function<void(string)> func1(hello); // 定义了一个函数对象,类型为void(string)func1("Hello, world!"); // func1.operator()("Hello, world!");return 0;
}

代码优化

如果我们要使用function来保存int sum(int a, int b)呢?我们岂不是又要实现一个特例化的模板类?答案肯定是不用!

void hello(string str) { cout << str << endl; }
int sum(int a, int b) { return a + b; }
int main () {function<void(string)> func1(hello); // func1 = hello;func1("hello world");function<void(int a, int b)> func2(sum);cout << func2(10, 20) << endl;return 0
}

可变参的函数对象

template<typename R, typename... Args> //可变参的类型参数
class my_function<R(Args...)> {
public:using PFUNC =  R (*) (Args...);my_function(PFUNC pfunc) : _pfunc(pfunc) {}R operator()(Args... args) const { return _pfunc(args...); } //hello(arg)
private:PFUNC _pfunc;
};
http://www.lryc.cn/news/342722.html

相关文章:

  • Linux学习之路 -- 文件 -- 文件描述符
  • JDK动态代理和Cglib动态代理区别
  • 牛客 | 字符金字塔
  • 【计算机科学速成课】笔记三——操作系统
  • 用js代码实现贪吃蛇小游戏
  • 微信小程序+esp8266温湿度读取
  • 软考中级-软件设计师(十)网络与信息安全基础知识
  • 推荐一个好用的命令行工具ShellGPT
  • Prompt提示词教程 | 提示工程指南 | 提示词示例 入门篇
  • uniapp + uView动态表单校验
  • 【Linux】HTTPS
  • 语音识别--使用YAMNet识别环境音
  • 前端JS必用工具【js-tool-big-box】,邮箱,手机,身份证号,ip地址等正则验证方法学习
  • notepad++安装 hex-editor插件
  • Ubuntu18.04设置SSH密钥登录
  • 自动化运维管理工具----------Ansible模块详细解读
  • 零基础代码随想录【Day27】|| 39. 组合总和,40.组合总和II, 131.分割回文串
  • 实验15 MVC
  • 《Python编程从入门到实践》day21
  • 上位机图像处理和嵌入式模块部署(树莓派4b镜像烧录经验总结)
  • 简单数据加解密,JS和JAVA同时实现
  • Android Framework中PackageManagerService的深度剖析
  • (AI Web、ChatGPT Native、Ai Loading、AI Tools、知豆AI)
  • VBA 批量处理Excel文件
  • PG实例连接访问控制
  • 2024-05-07 商业分析-如何在社会层面做一个更好的工具人-记录
  • C++设计模式-创建型设计模式
  • code-server容器webpack的ws无法连接解决方法
  • leetcode47-Permutations II
  • 246 基于matlab的交流电机动态方程