其实指针并不可怕,可怕的是你那一颗不自信的心和对于指针的畏惧! 说明,写在前面: .本文的内容严格按照C++标准而写,可能与C语言的标准有出入,C语言用户请只作参考。 .我书写了大量的代码用于验证本文内容的正确性,我所用的编译器是微软的Visual Studio 2010 SP1(中文旗舰版)和GNU的MinGW 20111108。 .若是读者也要写代码来验证本文内容的正确性,请使用和我同样的编译器或者使用一些版本较新的编译器。由于一些旧版本的编译器对C++标准的支持是不完整的,好比Visual C++ 6.0。用Visual C++ 6.0可能会对正确的标准C++代码报错,固然,对本文的内容仅是可能,而且可能性应该不大。个人Visual C++ 6.0装在虚拟机上,时间关系,没有在那上面测试本文的内容。 .个人测试代码暂时不提供给读者。 .若是没有学过C++,或者是C++初学者,或者对C++的掌握不是很精纯,那么,请不要先阅读本文,由于我怕打击你的信心。请达到必定水准后再来阅读本文。由于本文是C++的进阶文章。 正文: 在通向C++的道路上,函数与指针是不可缺乏的元素,那么,当二者邂逅时,又会发生什么呢,下面就让我带你走进它们的世界。 咱们将用五个部分来讲明几个重要的概念:返回指针的函数,指向函数的指针(函数指针),返回指向函数的指针的函数。 注意:C++容许函数在声明时不写形参的名字,而只写形参的类型,如: int abc(int i);在声明能够写为int abc(int); 所以本文的声明都省略形参名。但注意,在实现时是不能省略的。 .返回指针的函数和指向函数的指针(函数指针) 返回指针的函数声明示例以下: bool *pf(const string&, const string&); 这里,pf是一个函数,返回的是一个bool类型的指针。 指向函数的指针声明示例以下: bool (*pf)(const string&, const string&); 这里,pf是一个指针,指向的是一个函数。这个函数的返回类型是bool,并有两个const string型的引用形参。咱们把pf叫作一个函数指针。 .用typedef简化函数指针的定义及其初始化,赋值和使用。 函数指针类型至关冗长,使用typedef为指针类型定义同义词,可将函数指针的使用大大简化: typedef bool (*cmpFcn)(const string&, const string&); 这里,cmpFcn是一个函数指针类型,不是一个具体的指针。就像类和对象的关系同样。 如今能够用cmpFcn来定义指向返回类型是bool,并有两个const string型的引用形参的函数的指针了。 假设有一个函数: bool lengthCompare(const string&, const string&); 在标准C++中,除了用做函数的左操做数外,对函数名lengthCompare的任何使用都被解释为以下类型的指针 bool(*)(const string&, const string&); 显然这是一个函数指针。 所以,咱们能够这样: cmpFcn pf1=0;//正确。用0值为函数指针初始化。 cmpFcn pf2=lengthCompare;//正确。用同类型的函数名为函数指针初始化。 pf1=lengthCompare;//正确。用同类型的函数名为函数指针赋值。 pf2=pf1;//正确。用同类弄的函数指针为函数指针赋值。 我在上面的注释中反复强调同类型这个词,由于函数指针的初始化和赋值只能是0值表达式或者同类型的函数或者同类型的函数指针。例如假设有函数: string::size_type sumLength(const string&, const string&); bool cstringCompare(char*, char*); 对如下操做就有: cmpFcn pf; pf=sumLength;//错误。不是同类型。 pf=cstringCompare;//错误。不是同类型。 pf=lengthCompare;//正确.同类型。 注:引用函数名至关于对函数名应用取地址操做符,所以如下两句代码是等效的: cmpFcn pf1=lengthCompare; cmpFcn pf1=&lengthCompare; 使用函数指针的方法: 若 cmpFcn pf=lengthCompare; 则如下三句代码等效: lengthCompare("hi","bye"); pf("hi","bye"); (*pf)("hi","bye"); .函数指针用做函数的形参 函数指针是能够用做函数的形参的,而且这种形参有如下两种等效的写法: void useBigger(const string&, const string&, bool(const string&, const string&)); void useBigger(const string&, const string&, bool(*)(const string&, const string&)); 这里说明,标准C++容许将函数的形参定义为一个函数类型,可是这个函数类型必须是指向函数的指针,而不能是函数,所以上面中,编译器在编译时会将 bool(const string&, const string&));自动转换为 bool(*)(const string&, const string&)); 也就是说函数类型的形参所对应的实参将被自动转换为指向相应函数类型的指针。 可是有一点要注意,当返回的是函数时,一样的转换操做没法自动实现,而必须显示指明。 如: typedef int func(int*, int); //注意,上面定义的不是函数指针类型,并且普通函数类型 对以下操做有: void f1(func);//正确。函数类型func将自动转换为相应的函数指针类型 func f2(int);//错误。返回值是函数,自动转换失效。 func *f3(int);//正确。返回值是函数指针不是函数。 第二句第三句的区别就是,返回函数类型时是要转换为相应函数指针的,可是不是由编译器自动完成的,必须由程序员显示指明。 .返回指向函数的指针的函数 听起来太拗口了,可是在标准C++中,这是能够的,可是,正确地写出这种返回类型也是至关不容易的,我举个例子: int (*ff(int))(int*, int); 我来解释这个定义: ff(int) 这是将ff声明为一个函数,并带有一个int类型的形参。这个函数返回的是这样一个指针: int (*)(int*, int); 若是你前面的内容看懂了,就容易发现这就是前面说的一个函数指针。 如今二者一结合,就是返回指向函数的指针的函数,其本质是函数,而不是指针。 咱们一样能够用typedef来达到简化的目的。 typedef int (*PF)(int*, int); PF ff(int); .指向重载函数的指针 标准C++容许函数指针指向重载的函数,但函数指针的类型必须和重载函数的某一个版本精确匹配。举例说明: 如今有两个重载函数,声明以下: extern void ff(vector<double>); extern void ff(unsigned int); 那么函数指针 void (*pf1)(unsigned int)=&ff;//&ff能够写成ff,等效,前面讲过 将正确匹配函数void ff(unsigned int); void (*pf2)(int)=&ff;//错误。没有能够匹配的函数。 由于没有void ff(int);这样的函数 double (*pf3)(vector<double>)=&ff//错误。没有能够匹配的函数。 由于没有double ff(vector<double>);这样的函数。 本文完。 年04月28日 中国宁波