目录
一.指针函数
指针函数就是一个返回值类型为指针的函数,其本质为一个函数,只不过这个函数的返回值为一个指针,例如
#include<iostream>
int* Compare(int* a, int* b)
{
return *a >= *b ? a : b;
}
int main()
{
int* a = new int(10);
int* b = new int(20);
int* c = Compare(a, b);
std::cout<< *c << std::endl;
delete a;
delete b;
return 0;
}
Compare()函数的功能是比较两个指针指向内存块中存储数据的大小,其返回值为int类型的指针。
执行结果如下:
二.函数指针
1.函数指针的概念
函数指针,顾名思义其本质是一个指针,而这个指针指向一个函数。也就是说函数指针是一个指向函数的指针。为什么指针能够用指向函数呢?因为,函数的名字就代表这个函数的入口地址。例如:
#include<iostream>
int Sum(int a, int b)//int (*)(int,int)//_cdecl
{
std::cout << "int Sum(int,int)" << std::endl;
return a + b;
}
int main()
{
int(*FUNC)(int x , int y);
FUNC = Sum;//或者FUNC = &Sum
int a =FUNC(10, 20);//或者int a =(*FUNC)(10, 20);
std::cout << a << std::endl;
return 0;
}
这里的FUNC就是一个int*类型的函数指针,而它指向的函数为Sum(),Sum()函数的返回值为int类型,两个形参的类型也都是int类型。注意:函数指针所指向的函数一定要保持函数的返回值类型,函数参数个数,类型一致。
执行结果:
我们也可以使用typedef定义简化函数指针的定义,比如将上述代码改为:
typedef int(*FUNC)(int x , int y);
FUNC func = Sum;//或者FUNC func = &Sum
int a =func(10, 20);//或者int a =(*func)(10, 20);
std::cout << a << std::endl;
return 0;
这里定义了一个FUNC类型的函数指针func来指向Sun()函数,而这种定义方式也是我们经常用到的。
2.函数指针的应用
1.将函数指针作为参数传递给另一个函数。
#include<iostream>
int test(int a)
{
return a - 1;
}
int test2(int (*fun)(int), int b)
{
int c = fun(10) + b;
return c;
}
int main(int argc, const char* argv[])
{
typedef int (*fp)(int a);
fp f = test;
std::cout << test2(f, 1) << std::endl; // 调用 test2 的时候,把test函数的地址作为参数传递给了 test2
return 0;
}
2.利用函数指针,我们可以构成函数指针数组,更明确点的说法是构成指向函数的指针数组。
#include<iostream>
void t1() { std::cout << "test1" << std::endl; }
void t2() { std::cout << "test2" << std::endl; }
void t3() { std::cout << "test3" << std::endl; }
int main(int argc, const char* argv[])
{
typedef void (*fp)(void);
fp b[] = { t1,t2,t3 }; // b[] 为一个指向函数的指针数组
b[0](); // 利用指向函数的指针数组进行下标操作就可以进行函数的间接调用了
b[1]();
b[2]();
return 0;
}
执行结果:
3.指向类成员函数的函数指针
定义:类成员函数指针(member function pointer),是 C++ 语言的一类指针数据类型,用于存储一个指定类具有给定的形参列表与返回值类型的成员函数的访问信息。
基本上要注意的有两点:
- 1、函数指针赋值要使用 &
- 2、使用 .* (实例对象)或者 ->*(实例对象指针)调用类成员函数指针所指向的函数
#include<iostream>
class Test
{
public:
Test(int a) :ma(a) {}
int add(int b)
{
std::cout << "Test::add(int)" << std::endl;
return ma + b;
}
private:
int ma;
};
int main()
{
Test t(10);
Test* ptest = new Test(10);
typedef int (Test::* CPPFUNC)(int);
CPPFUNC cppfunc = &Test::add;
int a = (t.*cppfunc)(20);//t是Test类的一个对象,因此此时使用.*
std::cout << a << std::endl;
int b = (ptest->*cppfunc)(20);//ptest是Test类的一个指针,因此此时使用->*
std::cout << b << std::endl;
return 0;
}
我们注意到在定义函数指针CPPFUNC时,多了一个类作用域,这点需要特别注意。
执行结果:
总结:
类成员函数指针与普通函数指针不是一码事。前者要用 .* 与 ->* 运算符来使用,而后者可以用 * 运算符(称为"解引用"dereference,或称"间址"indirection)。
普通函数指针实际上保存的是函数体的开始地址,因此也称"代码指针",以区别于 C/C++ 最常用的数据指针。
而类成员函数指针就不仅仅是类成员函数的内存起始地址,还需要能解决因为 C++ 的多重继承、虚继承而带来的类实例地址的调整问题,所以类成员函数指针在调用的时候一定要传入类实例对象。