函数存放在内存的代码区域内,它们同样有地址.如果我们有一个 int test(int a) 的函数,那么,它的地址就是函数的名字,这一点如同数组一样,数组的名字就是数组的起始地址。
data_types (*func_pointer)( data_types arg1, data_types arg2, ...,data_types argn);
例如:
int (*fp)(int a); // 这里就定义了一个指向函数(这个函数参数仅仅为一个 int 类型,函数返回值是 int 类型)的指针 fp。
注意: 函数指针所指向的函数一定要保持函数的返回值类型,函数参数个数,类型一致。
执行以上代码,输出结果为:
10
定义: 类成员函数指针(member function pointer),是 C++ 语言的一类指针数据类型,用于存储一个指定类具有给定的形参列表与返回值类型的成员函数的访问信息。
基本上要注意的有两点:
1、函数指针赋值要使用 & 2、使用 .* (实例对象)或者 ->* (实例对象指针)调用类成员函数指针所指向的函数下面看两个例子:
对于 nonstatic member function (非静态成员函数) 取地址,获得该函数在内存中的实际地址
对于 virtual function(虚函数) , 其地址在编译时期是未知的,所以对于 virtual member function(虚成员函数)取其地址,所能获得的只是一个索引值
执行以上代码,输出结果为:
A::set(): 0x8048a38 B::print(): 0x1 B::print(): 0x5 A: 10 A: 100 A: 1000 A: 10000B) 类成员函数指针指向类中的静态成员函数
#include <iostream> using namespace std; class A{ public: //p1是一个指向非static成员函数的函数指针 void (A::*p1)(void); //p2是一个指向static成员函数的函数指针 void (*p2)(void); A(){ **指向非static成员函数的指针 **指向static成员函数的指针 **的变量的赋值方式是一样的,都是&ClassName::memberVariable形式 **区别在于: **对p1只能用非static成员函数赋值 **对p2只能用static成员函数赋值 **再有,赋值时如果直接&memberVariable,则在VS中报"编译器错误 C2276" **参见:http://msdn.microsoft.com/zh-cn/library/850cstw1.aspx p1 =&A::funa; //函数指针赋值一定要使用 & p2 =&A::funb; //p1 =&A::funb;//error //p2 =&A::funa;//error //p1=&funa;//error,编译器错误 C2276 //p2=&funb;//error,编译器错误 C2276 void funa(void){ puts("A"); static void funb(void){ puts("B"); int main() A a; //p是指向A中非static成员函数的函数指针 void (A::*p)(void); (a.*a.p1)(); //打印 A //使用.*(实例对象)或者->*(实例对象指针)调用类成员函数指针所指向的函数 p = a.p1; (a.*p)();//打印 A A *b = &a; (b->*p)(); //打印 A /*尽管a.p2本身是个非static变量,但是a.p2是指向static函数的函数指针, **所以下面这就话是错的! // p = a.p2;//error void (*pp)(void); pp = &A::funb; pp(); //打印 B return 0;类成员函数指针与普通函数指针不是一码事。前者要用 .* 与 ->* 运算符来使用,而后者可以用 * 运算符(称为"解引用"dereference,或称"间址"indirection)。
普通函数指针实际上保存的是函数体的开始地址,因此也称"代码指针",以区别于 C/C++ 最常用的数据指针。
而类成员函数指针就不仅仅是类成员函数的内存起始地址,还需要能解决因为 C++ 的多重继承、虚继承而带来的类实例地址的调整问题,所以类成员函数指针在调用的时候一定要传入类实例对象。
原文地址:https://blog.csdn.net/crayondeng/article/details/16868351


