本篇主要梳理下C语言中函数指针指向函数的三种形式,以及C++中函数指针与重载函数是如何结合的。
一、C语言中函数指针与函数的三种指向关系
我们先来定义一个函数,如下:
int fun(void)
{
printf("in fun\n");
return 0;
}
下面代码解释函数指针的三种定义方式
//函数指针指向函数的方式
//第一种方式:定义函数类型
typedef int (fun_t)(void);
//第二种方式: 定义函数指针类型
typedef int(*pFun_t)(void);
//第三种方式:直接定义出这种函数类型的指针的变量
int(*pFun3)(void) = NULL;
int main(void)
{
//第一种方式: 基于函数类型定义这种函数类型指针
fun_t *pFun1 = fun;
pFun1();
//第二种方式:直接定义该函数指针的类型
pFun_t pFun2 = fun;
pFun2();
//第三种方式:
pFun3 = fun;
pFun3();
return 0;
}
运行结果:
二、C++中函数重载和函数指针是如何结合的
1、我们知道,C++中是有函数重载的,函数重载有如下规则:
(1)、函数名相同。
(2)、参数个数不同,参数的类型不同,参数顺序不同,均可构成重载。
(3)、返回值类型不同则不可以构成重载,即判断函数重载的时候,不需要看返回值类型。
下面举几个例子:
void func(int a); //ok
void func(char a); //ok
void func(char a,int b); //ok
void func(int a, char b); //ok
char func(int a); //与第⼀个函数有冲突
2、C++中函数重载的底层实现:
C++利用 name mangling(倾轧)技术,在编译的时候,将重载函数通过内定法则,将重载函数编译成每个函数的唯一标识。
其实很简单,我们来看两个例子,例如C++中有三个重载函数:
void func(int a); ------------------------------------>在编译的时候会被处理成 fun_i(int a)
void func(char a); ----------------------------------->在编译的时候会被处理成func_c(char a)
void func(char a,int b,double c); --------------------------->在编译的时候会被处理成func_cid(char a,int b, double c)
根据以上例子,很容易推测出,用v c i f l d f分别表示void char int float long doouble。
3、理解了上面的就很容易理解C++中函数重载与函数指针的结合:
当时有重载函数名对函数指针进行赋值时,根据重载规则挑选与函数指针参数列表已知的候选者,严格匹配候选者的函数类型与函数指针的函数类型。例子:
#include <iostream>
using namespace std;
//定义三个重载函数
static int fun(int a)
{
cout << "in fun ----1" << endl;
return 0;
}
static int fun(int a,int b)
{
cout << "in fun ----2" << endl;
return 0;
}
static void fun(int a, const char *ps)
{
cout << "in fun ----3" << endl;
}
// 定义上函数指针类型和函数指针变量
typedef int(*pFun1)(int a);
typedef int(*pFun2)(int a,int b);
typedef void(*pFun3)(int a, const char *ps);
pFun1 p1 = NULL;
pFun2 p2 = NULL;
pFun3 p3 = NULL;
int main(void)
{
//三个函数指针变量分别指向重载函数
p1 = fun; //根据匹配规则,指针指向 int fun(int a)
p2 = fun;//根据匹配规则,指针指向 int fun(int a,int b)
p3 = fun;//根据匹配规则,指针指向void fun(int a, const char *ps)
p1(0);
p2(1,2);
p3(3,"abcd");
return 0;
}
运行结果:
总结: 重载函数本质上是相互独立的不同函数。