#include<iostream>
using namespace std;
int add(int a,int b){
return a+b;
}
int add2(int a,int b){
return a*2+b;
}
int deal(int a,int b,int (*pf)(int,int)){
return pf(a,b);
}
template<class A,class B,class F>
int deal(A a,B b,F func){
/**
* 参数列表最后的F func,也可以写成F& func
*/
return func(a,b);
}
int deal2(int a,int b,int (*func)(int,int) ){
return func(a,b);
}
int main(){
int (*pf)(int,int)=add; //函数指针第一种写法
cout<<pf(1,1);
using F=int(int,int); //感觉using和typedef差不多
F (*pf2)=add;
cout<<pf2(1,1); //函数指针声明的时候要用(*指针名),但是用的时候只需要 指针名,或者(*指针名)这样调用
cout<<(*pf2)(1,2); //不过我感觉pf2这种写法好一点,但是缺点是调用的时候不知道这个东西是函数指针还是函数
using byte=char; //对,using就和typedef差不多
byte a[10];
a[0]='3';
cout<<a[0];
typedef int(*D2)(int,int); //这样的typedef和一般的typedef不一样,一般的是typedef a b,使用b来代替a,再函数指针这里他把后面两个缩写到了一起
//typedef int(int,int) (*D3);//这样分开定义是会显示错误的,只能用下面decltype的形式,或者上面的using形式
typedef decltype(add) D; //这里用了自动类型推断decltype(add),这个结果也就是 int(int,int),因为一个函数指针指向的函数类型只和其返回值,参数列表有关
D (*pf3)=add;
pf3=add; //直接加函数名也可以
pf3=&add; //这样取地址也可以
cout<<(pf3)(1,2);
//上面说了,函数指针只和返回类型和参数列表有关,因此我们对于一个类型的函数,都可以把这些函数的地址放到同一个指针中
pf=add2;
pf2=add2;
pf3=add2;
cout<<pf(1,2)<<pf2(1,2)<<pf3(1,2);
//函数怎么当参数?
//有两个办法,第一个就是函数指针,第二个是C++模板
//假设我们实现一个函数,它可以通过我们传进去的两个数,再加一个传进去的函数,决定返回结果
//1.函数指针
int (*pf4)(int,int)=add;//1,获取函数地址,把他作为参数
cout<<deal(1,2,pf4); //直接传进去就可以了
//2.模板语法
//模板也是可以使用的,它可以自动推导第三个参数的类型为int(int,int),最后的结果就是 (int a,int b,int (*func)(int,int) )
cout<<deal(1,2,add);
cout<<deal2(1,2,add);
}