浅析C++的函数式编程

前言

Java8在Java中通过lambda表达式、Stream API引入了函数式编程,那么C++中是否也支持函数式编程呢?答案是肯定的。目前关于C++进行函数式编程的语法探究的相关博客、文章并不多,本篇博客的目的就是阐述利用C++进行函数式编程的几种方法。
为了避免本博客篇幅过大,本博客中只涉及C++函数式编程的语法,不对函数式编程的相关思想和关键概念进行详细阐述,但本博客的最后会给出笔者认为比较好的关于函数式编程的相关参考书籍。如有问题或发现本博客中涉及的bug可以在评论区中提出,谢谢!

阅读完本博客你将会理解和掌握:

  • 函数式编程简化代码、复用已有函数、降低编码复杂度的优点
  • 函数指针的声明和使用方法
  • lambda表达式的形式和用法
  • 利用函数指针和lambda表达式实现C++的函数式编程
  • 利用fuction<T>模板的声明和用法,并用fuction<T>模板替代函数指针
  • functional头文件中的函数对象和用法
  • 利用函数式编程对已有代码进行重构

一个简单的编程问题

我想大家在刚刚开始接触编程的时候应该都遇到过这样一个简单的编程问题:
给出3个int型整数abc,当:

  • c0时,求出a+b
  • c1时,求出a-b
  • c2时,求出a*b
  • c3时,求出a/b

看到这个问题,你会想到怎么实现呢?如果有了想法快去自己实现一下呀(~ ̄▽ ̄)~
我们的第一想法(好吧,只是我的第一想法)应该是用一个mapc值和对应的计算方式建立映射关系,显然这个方法目前不可行,因为C++中不支持定义“函数类型”。我们只能退而求其次,使用if-else语句或者switch-case-break语句来完成该程序,代码清单1如下:

//代码清单1
#include<iostream>
using namespace std;
int Plus(int a,int b){
   //加法
    return a+b;
}
int Minus(int a,int b){
   //减法
    return a-b;
}
int Multiplies(int a,int b){
   //乘法
    return a*b;
}
int Divides(int a,int b){
   //除法
    return a/b;
}
int main(){
   
    int a,b,c;
    cin>>a>>b>>c;
    if(c==0)
        cout<<Plus(a,b)<<endl;
    else if(c==1)
        cout<<Minus(a,b)<<endl;
    else if(c==2)
        cout<<Multiplies(a,b)<<endl;
    else if(c==3)
        cout<<Divides(a,b)<<endl;
    return 0;
}

显然这样的代码过于臃肿,不够简洁,如果我们可以用mapc值和对应的计算方式建立起映射关系,输入c,直接调用对应的函数,代码会简洁很多,那么我们有什么办法去实现这样的map吗?(当然有!不然我写这篇博客干啥︿( ̄︶ ̄)︿)

函数指针

C++中没有函数类型,但是有函数指针的概念,函数指针指向的是函数而非对象。和其他指针一样,函数指针也具有类型,其类型由指向函数的形参类型和返回类型共同决定。函数指针声明方式是函数返回类型 (*函数指针名) (形参类型列表),我们可以按照下面的声明方式声明一个函数指针:

//定义指向包含两个int形参,返回类型为int的函数的函数指针
int (*f)(int,int)=nullptr;//当前该函数指针没有指向任何一个函数

当我们把函数名作为一个值使用时,该函数名自动转换成指针,例如,我们可以这样让f指针指向我们上一个程序中定义的Plus函数(注意函数指针与函数的类型必须匹配):

f=Plus;//f指向名为Plus的函数
f=&Plus;//等价的赋值语句,取地址符是可选的

我们可以直接使用函数指针调用一个函数,无须解引用:

int t1=Plus(1,2);//调用Plus函数
int t2=f(1,2);//等价的调用语句

虽然我们不能将多个函数存放到一个数组中,但我们可以将多个函数指针存放在一个数组中,语法是函数返回类型 (*函数指针名[数组维度]) (形参类型列表),我们可以按照下面的声明方式声明一个4维的函数指针数组`:

int(*v[4])(int,int);

如何使用标准库中的容器,例如vectormap,可以按照下面的声明方式声明一个存放函数指针类型的vector以及存放int->函数指针键值对的map

vector<int(*)(int,int)>v;
map<int,int(*)(int,int)>m;

哇,好复杂的声明,难道我需要定义函数指针的地方,都要这么声明吗?当然不是,我们可以利用C++中的类型别名机制using来简化声明:

using pf=int(*)(int,int);//pf是该函数指针类型的一个别名
vector<pf>v;//存放函数指针的vector
map<int,pf>m;//存放`int->函数指针`键值对的`map`
pf f[4];//函数指针数组

因此我们可以利用下面的代码清单2解决刚刚提出的加、减、乘、除的编程问题:

//代码清单2
#include<iostream>
#include<map>
using namespace std;
int Plus(int a,int b){
   //加法
    return a+b;
}
int Minus(int a,int b){
   //减法
    return a-b;
}
int Multiplies(int a,int b){
   
  • 70
    点赞
  • 170
    收藏
    觉得还不错? 一键收藏
  • 21
    评论
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值