志在指尖
用双手敲打未来

函数指针(函数指针定义详解)

函数指针

1.指向一般函数的指针
很简单,如下的比方能够阐明基本格局和用法:
intint_add(inta,intb)
{
return(a+b);
}
intint_sub(inta,intb)
{
return(a-b);
}
int(*int_operator)(int,int)=int_add;
int_tmain(intargc,_TCHAR*argv[])
{
cout<int_operator=int_sub;
cout<return0;
}
上例中,int_operator会被编译器解释成类型int(*)(int,int)的一个指针。
调用方法还能够写作:(*int_operator)(4,5),这样的优点是让人一眼就能看到int_operator是一个函数指针。
留意:函数指针和指向函数的返回值的类型和参数都有必要严厉共同;
2.函数指针数组
我们还能够声明一个函数指针的数组,比方:
int(*pFuncArray[10])();
[]的优先级高于*,该语句将pFuncArray声明为拥有10个元素的数组,每一个元素都是指向一个函数的函数指针,该函数没有参数,返回值类型为int;
留意不能写作:int((*pFuncArray)[10])(),这样会产生编译过错;
(*pFuncArray)[10]标明晰pFuncArray是一个指针,该指针指向一个’含有10个元素的数组’;
其类型为int()(),明显,编译不能通过。
将上面的声明转换为typedef格局,会使程序可读性添加:
typedefint(*pFunc)();
pFuncpFuncArray[10];
如果需求调用其中的第三个函数,那么调用方法为:pFuncArray[2]();
3.指向‘函数指针数组’的指针
还能够声明一个指向‘函数指针数组’的指针,比方下面的比方代码:
intcmp_len(constchar*str1,constchar*str2)
{return((int)strlen(str1)-(int)strlen(str2));}
intcmp_str(constchar*str1,constchar*str2)
{returnstrcmp(str1,str2);}
typedefint(*PCMP_FUNC)(constchar*,constchar*);
PCMP_FUNCpCmpFuncs[2]=
{
cmp_len,
cmp_str,
};
//声明指向pCmpFuncs的指针
PCMP_FUNC(*ppCmps)[2]=&pCmpFuncs;
声明分化阐明如下:
(*ppCmps):标明ppCmps是一个指针;
(*ppCmps)[2]:后边紧跟[2],标明ppCmps是一个指向‘两个元素数组’的指针
PCMP_FUNC标明晰该数组元素的类型,它是指向函数的指针,返回值为int,有两个constchar*类型的参数;
实际上语句PCMP_FUNC(*ppCmps)[2]=&pCmpFuncs;
将会被编译器解释为:
int(*(*ppCmps)[2])(constchar*,constchar*)=&pCmpFuncs;
声明分化:
(*ppCmps):标明ppCmps是一个指针;
(*ppCmps)[2]:后边紧跟[2],标明ppCmps是一个指向‘两个元素数组’的指针
int(*)(constchar*,constchar*):标明晰该数组元素的类型,它是指向函数的指针,返回值为int,有两个constchar*类型的参数;
3.函数指针与类
在C++语言中,运用函数指针能够指向类的一个成员函数或变量,尽管这种用法很少能用到,至少我是没有用过,不过了解一下还是有点必要的。
为了支撑这类指针,C++有三个特殊的运算法符:::*,.->,.*;
指向成员函数的指针有必要与向其赋值的函数类型匹配,这包括:1)参数的类型和个数;2)返回值类型;3)它所属的类型;
指向成员变量的指针有必要与向其赋值的变量类型匹配,这包括:1)变量类型;2)它所属的类型;
成员函数和变量有必要被绑定到一个目标或许指针上,然后才干得到调用目标的this指针,然后才干指向成员变量或函数;
类AClass的成员变量intm_iValue,其完好类型是:int型的类AClass的成员m_iValue;
类AClass的成员函数intAdd(int),其完好类型是:返回值为int型,带一个int类型参数的类AClass的成员Add;
留意:指向类的静态变量或静态成员函数的指针和一般成员不同;
3.1指向类成员变量的指针
有了上面的一些阐明,看下面的比方就很简单理解了;
.*是一个新的操作符,标明是指向成员操作符的指针(另一个是->*,是指针目标的调用方法
classAClass
{
public:
voidAdd(inta){m_iValue+=a;}
intm_iValue;
};
int_tmain(intargc,_TCHAR*argv[])
{
AClassa;
//声明并指向AClass的一个成员变量的指针
intAClass::*pValue=&AClass::m_iValue;
//或许如下方法:
//intAClass::*pValue;//指针变量声明
//pValue=&AClass::m_iValue;//指向A的m_iValue成员
a.*pValue=4;//运用方法,赋值
cout<return0;
}
3.2指向类成员函数的指针
有了上面的一些阐明,看下面的比方就很简单理解了;
下面的比方中,留意调用方法:(a.*pAAdd)(5);不能写作a.*pAAdd(5);
因为操作符()的优先级是高于.*的因而,它将被解释为a.*(pAAdd(5));明显这是不被支撑的。
classAClass
{
public:
voidAdd(inta){m_iValue+=a;}
intm_iValue;
};
//指向类AClass成员函数的指针的声明方法
typedefvoid(AClass::*pAFunc)(int);
//声明一个指向AClass::Add()的函数指针
pAFuncpAAdd=&(AClass::Add);
int_tmain(intargc,_TCHAR*argv[])
{
AClassa;
//声明并指向AClass的一个成员变量的指针
intAClass::*pValue=&AClass::m_iValue;
//或许如下方法:
//intAClass::*pValue;//指针变量声明
//pValue=&AClass::m_iValue;//指向A的m_iValue成员
a.*pValue=4;//运用方法,赋值
cout<(a.*pAAdd)(5);//指向成员函数指针的调用方法
cout<return0;
}
3.3指向类静态成员的指针
类的静态成员归于该类的全局目标和函数,并不需求this指针;因而指向类静态成员的指针声明方法和一般指针相同。
该类指针和一般指针的声明和调用方法完全相同;唯一的不同便是设置指向的目标时,仍然需求类信息,这一点和指向一般成员的指针相同。
下面的比方能够阐明运用方法。
classAClass
{
public:
staticvoidAdd(inta){m_iValue+=a;}
staticintm_iValue;
};
intAClass::m_iValue;
typedefvoid(*pAAdd)(int);
int_tmain(intargc,_TCHAR*argv[])
{
//声明并指向AClass的一个静态成员变量的指针
int*pValue=&AClass::m_iValue;
//或许如下方法:
//int*pValue;//指针变量声明
//pValue=&AClass::m_iValue;//指向A的m_iValue成员
*pValue=4;//运用方法同一般指针,赋值
cout<<*pValue<pAAddp=&AClass::Add;
p(5);//调用方法同一般函数指针
cout<<*pValue<return0;
}

函数
函数指针定义详解

假如在程序中界说了一个函数,那么在编译时系统就会为这个函数代码分配一段存储空间,这段存储空间的首地址称为这个函数的地址。并且函数名表明的便是这个地址。既然是地址咱们就能够界说一个指针变量来寄存,这个指针变量就叫作函数指针变量,简称函数指针。
那么这个指针变量怎样界说呢?虽然同样是指向一个地址,但指向函数的指针变量同咱们之前讲的指向变量的指针变量的界说方法是不同的。例如:
int(*p)(int,int);
这个句子就界说了一个指向函数的指针变量p。首要它是一个指针变量,所以要有一个“*”,即(*p);其次前面的int表明这个指针变量能够指向返回值类型为int型的函数;后边括号中的两个int表明这个指针变量能够指向有两个参数且都是int型的函数。所以合起来这个句子的意思便是:界说了一个指针变量p,该指针变量能够指向返回值类型为int型,且有两个整型参数的函数。p的类型为int(*)(int,int)。
所以函数指针的界说方法为:
函数返回值类型(*指针变量名)(函数参数列表);
“函数返回值类型”表明该指针变量能够指向具有什么返回值类型的函数;“函数参数列表”表明该指针变量能够指向具有什么参数列表的函数。这个参数列表中只需求写函数的参数类型即可。
咱们看到,函数指针的界说便是将“函数声明”中的“函数名”改成“(*指针变量名)”。可是这儿需求注意的是:“(*指针变量名)”两端的括号不能省掉,括号改变了运算符的优先级。假如省掉了括号,就不是界说函数指针而是一个函数声明了,即声明了一个返回值类型为指针型的函数。
那么怎样判断一个指针变量是指向变量的指针变量仍是指向函数的指针变量呢?首要看变量名前面有没有“*”,假如有“*”说明是指针变量;其次看变量名的后边有没有带有形参类型的圆括号,假如有便是指向函数的指针变量,即函数指针,假如没有便是指向变量的指针变量。
最后需求注意的是,指向函数的指针变量没有++和–运算。
如何用函数指针调用函数
给我们举一个比如:
intFunc(intx);/*声明一个函数*/
int(*p)(intx);/*界说一个函数指针*/
p=Func;/*将Func函数的首地址赋给指针变量p*/
赋值时函数Func不带括号,也不带参数。由于函数名Func代表函数的首地址,因而经过赋值以后,指针变量p就指向函数Func()代码的首地址了。
下面来写一个程序,看了这个程序你们就了解函数指针怎样使用了:
#include
intMax(int,int);//函数声明
intmain(void)
{
int(*p)(int,int);//界说一个函数指针
inta,b,c;
p=Max;//把函数Max赋给指针变量p,使p指向Max函数
printf(“pleaseenteraandb:”);
scanf(“%d%d”,&a,&b);
c=(*p)(a,b);//经过函数指针调用Max函数
printf(“a=%d\nb=%d\nmax=%d\n”,a,b,c);
return0;
}
intMax(intx,inty)//界说Max函数
{
intz;
if(x>y)
{
z=x;
}
else
{
z=y;
}
returnz;
}
输出结果是:
pleaseenteraandb:34
a=3
b=4
max=4
【常识扩展】
指针是C言语的精华,也是C言语的难点,没学会指针便是没学会C言语。假如你觉得函数指针还能勉强承受的话,能够尝试了解一些更杂乱的指针,例如:
char*(*c[10])(int**p);
int(*(*(*pfunc)(int*))[5])(int*);
以上两个指针能剖析清楚的话,那么99%的C言语指针问题都难不住你。
实际上,理清楚杂乱的C言语指针结构是有窍门的,只要掌握了窍门,再杂乱的指针也是能够了解的,感兴趣的读者请猛击这儿了解概况。

未经允许不得转载:IT技术网站 » 函数指针(函数指针定义详解)
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!

 

志在指尖 用双手敲打未来

登录/注册IT技术大全

热门IT技术

C#基础入门   SQL server数据库   系统SEO学习教程   WordPress小技巧   WordPress插件   脚本与源码下载