类型名 函数名(函数参数列表);
其中,后缀运算符括号“()”表示这是一个函数,其前缀运算符星号“”表示此函数为指针型函数,其函数值为指针,即它带回来的值的类型为指针,当调用这个函数后,将得到一个“指向返回值为…的指针(地址),“类型名”表示函数返回的指针指向的类型”。
“(函数参数列表)”中的括号为函数调用运算符,在调用语句中,即使函数不带参数,其参数表的一对括号也不能省略。其示例如下:
int pfun(int, int);
由于“”的优先级低于“()”的优先级,因而pfun首先和后面的“()”结合,也就意味着,pfun是一个函数。即:
int (pfun(int, int));
接着再和前面的“”结合,说明这个函数的返回值是一个指针。由于前面还有一个int,也就是说,pfun是一个返回值为整型指针的函数。
返回类型可以是任何基本类型和复合类型。返回指针的函数的用途十分广泛。事实上,每一个函数,即使它不带有返回某种类型的指针,它本身都有一个入口地址,该地址相当于一个指针。比如函数返回一个整型值,实际上也相当于返回一个指针变量的值,不过这时的变量是函数本身而已,而整个函数相当于一个“变量”。例如下面一个返回指针函数的例子: #include <stdioh> float find(float(pionter)[4],int n);//函数声明 int main(void) { static float score[][4]={{60,70,80,90},{56,89,34,45},{34,23,56,45}}; float p; int i,m; printf(Enter the number to be found:); scanf(%d,&m); printf(the score of NO%d are:\n,m); p=find(score,m-1); for(i=0;i<4;i++) printf(%52f\t,(p+i)); return 0; }float find(float(pionter)[4],int n)/定义指针函数/ { float pt; pt=(pionter+n); return(pt); }共有三个学生的成绩,函数find()被定义为指针函数,其形参pointer是指针指向包含4个元素的一维数组的指针变量。pointer+n指向score的第n+1行。(pointer+1)指向第一行的第0个元素。pt是一个指针变量,它指向浮点型变量。main()函数中调用find()函数,将score数组的首地址传给pointer
std::function其实就是一个 类模板 ,含有c的 函数指针 概念。
类模版std::function是一种通用、多态的函数封装。std::function的实例可以对 任何可以调用的目标实体 进行存储、复制、和调用 *** 作,这些目标实体包括普通函数、Lambda表达式、函数指针、以及其它函数对象等。
简要来说:std::function是将所有可调用的实体封装起来,形成了一个新的std::function对象,用户在使用的时候不需要再去一一调用实体,只需要使用新的std::function来调用各实体
如下,std::function作为 回调函数 使用,它可以调用任何有两个int形参的返回值为int的对象
又因为std::function兼容c的函数指针,所以它还包含函数指针应有的特性。但是它又和函数指针不同,函数指针只能指向一个函数,而 std::function可以指向任何可以被当做函数调用的对象
以下内容来自
因为调用initWithFunction会产生临时的std::function对象,属于右值,必须使用const,不然会报错
转移 *** 作std::move效率更高
std::bind完成了实体和函数地址的绑定,因为它的参数里面既有对象指针,又有函数指针,从而制造了一个std::function,然后std::function只要能正确处理那个this指针,那就能完成正确地调用了
bind是一种机制,可以预先把指定的可调用的实体的某些参数绑定到已有的变量,产生一个新的可调用实体。
它作为一个通用函数适配器,接收一个可调用对象,生成一个新的可调用对象来 适应原对象的参数列表 。
比如,存在一个这样的函数check_size,因为这是一个二元函数,当我们要将它作为find_if的参数,会出错。因为find_if只接受一元函数,那么如何解决呢?
一个方法是Lambda表达式,还有一个方法就是使用std::bind
下面这个bind的函数只有一个占位符,即只需要传入一个参数。它将check_size的第二个参数绑定在sz上,sz的值就是check_size的第二个参数的值,而check_size第一个参数需要传入
如果现在我们调用g(3,5),那么就相当于bind(f,a,b,5,c,3);
所以_1相当于传递的第一个参数,_2相当于传递的第二个参数以此类推。
需要注意: bind对于直接绑定的值,是以值传递的方式,对于用_1这类,是使用引用传递。bind的返回值是可以调用的实体,所以通常我们都会将它和function联合在一起使用。
有时候对于有些绑定的参数我们希望以引用方式传递,或者说要绑定的参数无法拷贝。
比如ostream 流对象是无法拷贝 的,那么我们希望将它传递给bind而不拷贝它,就需要使用 ref 。
ref返回一个对象,包含给定的引用,是可以拷贝的。
对于成员函数的绑定,我们一定需要一个调用者,也就是类的实例!
需要注意的是,bind 无法绑定重载函数 ,因为当重载函数的参数个数不相同时,bind也失去了它的意义。
在cocos2dx的源码中,我们经常可以看到function作为函数形参,而bind作为实参传入
//数组传递给函数时会退化成指针
#include<iostream>
using namespace std;
template<int m>
void func(int (&array)[m])
{
}
int main()
{
int a[2]={0,1};
func(a);
}
// c++ 要求模板参数推导成功后,才能实例化生成函数进行调用。
//在决定函数类型时,数组统统弱化为指针,所以 int a [m],就是 int a,问题就在于 m 变没了,因此不可能从实参中推导了(因为没有必要),这样模板非类型形参 m 就推不出来了,所以只能自己指定。
//int (&a) [m] 不存在弱化的问题,所以 m 能够从实际调用中推出。
//其实模板也可以不用引用的。
#include<iostream>
using namespace std;
template<int m=0>
void func(int array [m]){
}
int main(){
int a[2]={0,1};
func(a);
}
c++11才支持函数模板默认参数
lambda表达式 是一个匿名函数,也就是没有函数名的函数。也叫闭包,闭就是封闭的意思,包就是函数。lambda表达式 其实就是一个函数对象,内部创建了一个重载() *** 作符的类。
捕获变量列表 -> 返回值类型(函数主体) ,lambda可以隐士返回,也就是返回值类型可以不用显示写出来。
c++和c#不一样,想在闭包里面使用外部变量,就必须先在捕获变量列表里面定义。有下面几种定义可供选择。
[]没有捕获任何变量
[=] 按值类型捕获Lambda 所在范围内所有可见的局部变量
[&] 按引用类型捕获Lambda 所在范围内所有可见的局部变量
[a] 按值类型捕获a变量
[&a] 按引用类型捕获a变量
[&,a] 值类型捕获a,引用类型捕获其余变量
[=,&a] 引用类型捕获a,其余按值类型捕获
[this] 可以使用 Lambda 所在类中的成员变量。
当然参数也可以是多个,比如[a,b,c,&d] [&a,b,&c,d]这样都是可以的。
注意一点,变量捕获是在lambda表达式被创建的时候。
函数指针就是即指向函数的指针。
定义格式一般是 返回值类型(函数指针名字)(参数),例如 int ( p)(int) double ( p)(string) void(p)(int)都是正确的函数指针定义。
下面看一个向函数指针传递lambda的例子:
输出结果为 1,在这里我们并没有用到变量捕获, 事实上c++不允许往函数指针传递lambda的时候进行变量捕获。 下面介绍function。
类模板std :: function是一个通用的多态函数包装器。 std :: function的实例可以存储,复制和调用任何可调用的目标 :包括函数,lambda表达式,绑定表达式或其他函数对象,以及指向成员函数和指向数据成员的指针。(这句话是我抄的)
function声明格式 function<返回值(变量类型)>,例如function<int(int)>,function<void(int)>都是function的正确声明。
上面定义了一个返回值为void,接受一个int类型参数的function函数模板,右边是一个lambda表达式,值类型捕获a,输出的结果是func1 a=0 b=5。
再看下面一种情况
定义了一个返回值为void,接受一个int类型参数的function函数模板,显式返回a+b的值,输出5;
再看下面的情况
定义了一个返回值为void,按引用捕获a变量,接受一个int类型参数的function函数模板,隐式返回void,输出5,并且在最后改变了a的值a+=5。
细心的同学会发现,明明先调用了func3,后调用func2,为什么2还是输出5,那是因为捕获变量发生在lambda被创建的时候,把func2改成按类型捕获,或者将func3的声明和调用放到func2的前面,都会输出10。这一点还是要多多注意
没说清楚。DepthFirstVisit是什么?哪些函数是虚函数?函数指针要存起来吗?如果只是声明模板成员函数,很简单
class test{template<class T>
void foo(T t);
};
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)