一. 函数的类型和地址
函数也是有类型的,函数的类型由它的返回类型和形参类型共同决定,与函数名无关. 比如下面的函数的类型
bool lengthCompare(const string & a,const string & b);
该函数的类型是bool (const string&,const string&); 和变量一样,函数有固定的地址,直接打印函数名,或者函数的取地址符号,都能打印函数的地址.
#include <iostream>
using namespace std;
void func(void)
{
}
int main()
{
cout << "直接通过名称打印地址: " << func << endl;
cout << "通过地址符号打印地址: " << &func << endl;
cout << "通过解引用法打印地址: " << *func << endl;
cout << (func == &func) << endl;
cout << (&func == *func) << endl;
system("pause");
return 0;
}
从上面的例子可以看出来: func函数名称 和&func以及*func代表的意思都是一样的,都表示的是一个地址,指向保存函数的地址.
二. 函数指针的定义方式
① 函数指针的声明
把函数名替换为指针变量,就是声明一个可以指向该函数的指针.
bool (*pf)(const string&,const string&);
pf指向一个函数,该函数的参数是两个const string的引用,返回值是bool类型
*pf 两边的括号不能少,如果不写括号,则pf 是一个返回值为bool指针的函数
bool *pf(const string&,const string&);
② 当我们把函数名作为一个值使用时,该函数自动转换为指针
int (*funcPtr)();
int (*const funcPtr)();
#include <iostream>
using namespace std;
int foo()
{
cout << "foo() 函数被调用!" << endl;
return 100;
}
int func()
{
cout << "func() 函数被调用!" << endl;
return 200;
}
int main()
{
int (*funcPtr)() = foo;
funcPtr();
(*funcPtr)();
funcPtr = func;
funcPtr();
(*funcPtr)();
system("pause");
return 0;
}
结果:
③ 函数指针在使用的时候注意事项
1. 函数指针声明的形参和返回类型必须和指向的那个函数的形参和返回类型一样,如果不一样就会报错
#include <iostream>
using namespace std;
int func(int a)
{
cout << "func() 被调用!" << endl;
return a;
}
void func_1(int a)
{
cout << "func_1() 被调用!" << endl;
}
int main()
{
int (*funcPtr)(int a);
funcPtr = func;
funcPtr(10);
void (*funcPtr1)(int a);
funcPtr1 = func_1;
funcPtr1(10);
system("pause");
return 0;
}
2. 重载函数的指针
当我们使用重载函数的时候,上下文必须清晰地界定到底应该选用哪个函数.
void func(int*);
void func(unsigned int);
void (*pf1)(unsigned int) = func;
void (*pf2)(int) = func;
double (*pf3)(int*) = func;
三. 函数指针形参和返回值
① 形参可以是指向函数的指针,形参看起来是函数类型,实际上却是当成指针来使用
有两种方式声明:
- 直接使用函数类型,会自动转换成指向函数的指针
- 显示的将形参定义成指向函数的指针
#include <iostream>
using namespace std;
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
void func(int e, int d, int foo(int a, int b))
{
cout << "函数调用结果: " << foo(e, d) << endl;
}
void func_02(int e, int d, int (*foo)(int, int))
{
cout << "函数调用结果: " << foo(e, d) << endl;
}
int main()
{
func(10, 20, add);
func_02(10, 20, sub);
system("pause");
return 0;
}
② 返回指向函数的指针
- 首先返回值不能是一个函数,但是可以值返回指向函数类型的指针.
- 我们必须要将返回类型写成指针的形式,编译器不会自动地将函数返回类型当成对应的指针类型来处理.
using F = int(int*,int);
using PF = int(*)(int*,int);
必须时刻注意: 函数的返回类型必须显示的转换为函数指针类型编译器不会自动进行转换
PF f1(int);
F f1(int);
F * f1(int);
四. 使用typedef 来定义函数类型以及函数指针类型
typedef bool Func(const string&,const string&);
typedef decltype(lengthCompare) Func2;
typedef bool(*FuncP)(const string&,const string&);
typedef decltype(lengthCompare) * *FuncP2;
上例中, Func 和Func2 是函数类型,而FuncP 以及FuncP2 是指针类型.注意decltype()是返回函数的类型,此时不会将函数类型转换为指针类型.
void useBigger(const string&,const string&,Func);
void useBigger(const string&,const string&,FuncP2);
#include <iostream>
using namespace std;
typedef int (*funcPtr)(int, int);
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
int mul(int a, int b)
{
return a * b;
}
int divison(int a, int b)
{
return b ? a / b : -1;
}
funcPtr calc_func(char op)
{
switch (op)
{
case '+':
return add;
case '-':
return sub;
case '*':
return mul;
case '/':
return divison;
default:
return NULL;
}
}
int (*s_calc_func(char op)) (int, int)
{
return calc_func(op);
}
int calc(int a, int b, char op)
{
funcPtr fp = calc_func(op);
int (*s_fp)(int, int) = s_calc_func(op);
cout << "fp: " << fp << ",s_fp: " << s_fp << endl;
return fp(a, b);
}
int main()
{
int a = 100, b = 200;
cout << a << '+' << b << "=" << calc(a, b, '+') << endl;
cout << a << '-' << b << '=' << calc(a, b, '-') << endl;
cout << a << "*" << b << '=' << calc(a, b, '*') << endl;
cout << a << "/" << b << "=" << calc(a, b, '/') << endl;
system("pause");
return 0;
}
结果:
|