转载请标明是引用于 http://blog.csdn.net/chenyujing1234
欢迎大家提出意见,一起讨论!
最近在代码中看到指针的调用方式,有些疑问,于是在论坛上发了问题
现在对这个问题做个总结。
1、 函数指针的传递的两种环境(类成员函数)
运行的结果是:
I am function_One_Instance
I am function_Second_Instance
下面是原代码:
// ================================类里的函数指针调用方法====================================
class CTestFun
{
public:
// 测试函数
void testFunction(void)
{
// 方法一的使用
function_One_User(function_One_Instance);
// 方法二的使用
function_Second_User(&CTestFun::function_Second_Instance);
}
protected:
// ================================法一:====================================
/*****************************************************************************
总结:如果函数实例没有定义成static形式,那么:
(1)那么函数指针的声明得加类空间名字;
(2)在函数实例使用者内部得用this->来引用到函数指针
(3)在函数实例使用者的参数处得使用 CTestFun:来引用函数实例。
*/
// 函数类型定义
// 下面两名等价于 typedef void (*PFunction_One)();
typedef void function_One();
typedef function_One *PFunction_One;
// 函数实例
static void function_One_Instance()
{
printf("I am function_One_Instance\n");
}
// 函数使用者
void function_One_User(PFunction_One function)
{
function();
}
// ================================法二:=====================================
/*****************************************************************************
总结:如果函数实例没有定义成static形式,那么:
(1)那么函数指针的声明得加类空间名字;
(2)在函数实例使用者内部得用this->来引用到函数指针
(3)在函数实例使用者的参数处得使用 CTestFun:来引用函数实例。
*/
// 函数类型定义
// 定义一个原型为BOOL Fun(int a);的函数指针
typedef BOOL (CTestFun::*function_Second)(int);
// 函数实例
BOOL function_Second_Instance(int candidate)
{
printf("I am function_Second_Instance\n");
return TRUE;
}
// 函数使用者
BOOL function_Second_User(function_Second function)
{
// function其实是函数的指针
// 这里的"*function"是指找到function在类中的函数地址。
// 不是表明function是函数的指针的指针
// 一句话,使用类成员函数指针必须有“->*”或“.*”的调用
if ( (this->*function)(1) == TRUE )
return FALSE;
return TRUE;
}
};
int main()
{
CTestFun testFun;
testFun.testFunction();
system("pause");
return 0;
}
对于上面列出的代码,我的问题是:
1、把
if ( (this->*function)(1) == TRUE )
改为
if ( (/*this->*/*function)(1) == TRUE )
就会报错:
error C2171: “*”: “CTestFun::function_Second”类型的操作数非法
error C2064: 项不会计算为接受 1 个参数的函数
2、
若改为
if ( (/*this->**/function)(1) == TRUE )
就会报错:
error C2064: 项不会计算为接受 1 个参数的函数
这是为什么呢? 为什么一定要加this.
1、2两个问题是同一个问题。
答:
如果函数实例没有定义成static形式,那么:
(1)那么函数指针的声明得加类空间名字,以此具有全局属性。
(2)在函数实例使用者内部得用this->来引用到函数指针
(3)在函数实例使用者的参数处得使用 CTestFun:来引用函数实例。
3、BOOL function_Second_User(function_Second function)
中的形参是函数指针而已。
而调用的时候为什么是
function_Second_User(&CTestFun::function_Second_Instance); (加了& ,即函数的指针的指针)
4、 void function_One_User(PFunction_One function)
中的形参是函数的指针的指针,
而调用时为什么是
function_One_User((PFunction_One)function_One_Instance);
只是函数指针?
3、4 其实是同一个问题。
答:
由于加了CTestFun::来引用类中的函数成员
所以加上 &。一句话,这是类中的规定。
1、1 获得类中的函数指针,然后使用此函数
代码如下:
#include <stdio.h>
#include <windows.h>
typedef void (*PFunction_One)();
class AA
{
public:
void func()
{
printf("I am in AA.func()\n");
}
};
int main()
{
AA aA;
PFunction_One tempFun = aA.func;
tempFun();
system("pause");
return 0;
}
编译后会出错:
1>c:\users\chenyj\desktop\test\main.cpp(23) : error C3867: “AA::func”: 函数调用缺少参数列表;请使用“&AA::func”创建指向成员的指针
修改为:
#include <stdio.h>
#include <windows.h>
typedef void (*PFunction_One)();
class AA
{
public:
static void func()
{
printf("I am in AA.func()\n");
}
};
int main()
{
AA aA;
PFunction_One tempFun = AA::func;
tempFun();
system("pause");
return 0;
}
此时编译成功,且结果正常。
1、2 C++获取类成员函数的指针
参考: http://blog.csdn.net/wulibin136/article/details/6328992
class A
{
public:
static void staticmember(){cout<<"static"<<endl;} //static member
void nonstatic(){cout<<"nonstatic"<<endl;} //nonstatic member
virtual void virtualmember(){cout<<"virtual"<<endl;};//virtual member
};
int _tmain(int argc, _TCHAR* argv[])
{
A a;
//static member,取得的是该函数在内存中的实际地址,而且因为static成员是全局的,所以不能用A::限定符
void (*ptrstatic)() = &A::staticmember;
//nonstatic member 取得的是该函数在内存中的实际地址
void (A::*ptrnonstatic)() = &A::nonstatic;
//虚函数取得的是虚函数表中的偏移值,这样可以保证能过指针调用时同样的多态效果
void (A::*ptrvirtual)() = &A::virtualmember;
//函数指针的使用
ptrstatic();
(a.*ptrnonstatic)();
(a.*ptrvirtual)();
}
2、 函数指针的传递的两种环境(全局函数)
// ================================全局时函数指针调用方法====================================
/*****************************************************************************
总结:由于在全局的函数都默认是加了static的。
*/
// 定义一个原型为int Fun( int a );的函数指针
typedef int (*PTRFUN)(int aPara);
// pFun 为函数指针变量名
PTRFUN pFun;
// pFun2也是函数指针变量名
int (*pFun2)(int a);
// 定义回调函数
int CallBack(int a)
{
printf("I am CallBack\n");
return ++a;
}
// 定义回调者函数
void Caller( PTRFUN cb )
// void Caller( int (*cb) ( int ) ) // 也可这样申明
{
int nPara = 1;
int nRet = cb( nPara );
}
// 使用回调
void TestFunP()
{
Caller(CallBack); // 直接使用回调函数
PTRFUN cb = CallBack; // int (*cb) ( int ); cb = CallBack;
int nRet1 = cb( 99 ); // nRet1 = 100;
}
// ================================函数指针的指针使用========================================
// 定义函数指针的指针
typedef int (**PTRPTRFUN)(int aPara);
// 函数指针的指针作为参数
void PtrCaller(PTRPTRFUN cb)
// void PtrCaller( PTRFUN* cb ) // 指针申明
// void PtrCaller( int (**cb) ( int ) ) // 原型申明
{
int nRet = (*cb)(999); // nRet = 1000;
}
// 使用函数指针的指针
void TestFunPP()
{
PTRFUN cb = CallBack;
PtrCaller( &cb );
}
// ================================函数指针数组的使用========================================
// 函数指针数组的定义
PTRFUN fArray[10];
// int (*fArray[10])(int); // 原型定义
void TestFunPArray()
{
for ( int i = 0; i < 10; i++ )
{
fArray[i] = CallBack;
int nRet = fArray[i](i); // nRet = i+1;
}
}
// ================================函数指针与typedef========================================
// 形式一:
// 定义了一个指针变量pFun1
// 它是一个指向某种函数的指针
char (*pFun1)(int);
// 定义一个函数。
// 函数的函数名实际上就是一个指针,函数名指向该函数的代码在内存中的首地址
char glFun(int a){ return 1;}
void testF1()
{
pFun1 = glFun;
// 取pFun1所指向的地址的内容,当然就是取出了glFun()的内容
(*pFun)(2);
}
// 形式二:typedef 返回类型(*新类型)(参数表)
// typedef char (*PTRFUN)(int);
// PTRFUN pFun;
// char glFun(int a){ return;}
// void main()
// {
// pFun = glFun;
// (*pFun)(2);
// }
三、
1、
按以下的方法声明一个函数
VOID _stdcall (*process)(DWORD openHandle,
UINT event,
LPVOID pData,
UINT32 dataLength,
UINT32 totalLength,
UINT32 dataFlags);
编译时会报错:
: error C2059: 语法错误 : “(”
: error C2238: 意外的标记位于“;”之前
改为下面就不会了
VOID (_stdcall *process)(DWORD openHandle,
UINT event,
LPVOID pData,
UINT32 dataLength,
UINT32 totalLength,
UINT32 dataFlags);