先说一下C式的函数
指针。这种
函数指针的应用十分广泛。
对于任何
函数 void print(string s),它的
指针这样定义:
void (*pfun)(string) = NULL;
pfun= &print;
或者 pfun = print;两种写法没有区别。
pfun是
指针变量名。可以指向任何只带一个string参数,返回void的函数。这里让它指向print()
函数。
以后调用它的时候直接写
if (pfun)
pfun("Hello world");
C++编译器会通过pfun找到print
函数,然后callprint("Hello world");
一个简单应用是可以作菜单操作。例如在文本模式下的界面,让用户选择如下操作:
"0.print, 1.copy, 2.delete, 3. quit, 4.help"
那么可以写5个
函数:
void print();
void copy();
void delete();
void quit();
void help();
然后用一个
函数指针数组把他们存在一起:
void (*p[])() = {print, copy, delete, quit, help};
然后根据用户入0,1,2,3,4来直接叫
函数cin >> index;
p[index]();
在windows环境下编译这种
函数指针被认为是用C/C++呼叫规则(C/
C++ calling convention)。就是呼叫函数caller清理函数呼叫时生成的stack。另一种规则叫标准呼叫规则(standard calling convention)。由被叫函数callee清理自己的stack。二者一般情况下区别不大,但standard calling convention更合理,因为这样使
函数size变小了一点。
实际上写C/
C++函数指针的时候省略了 __cdecl 前缀。 应该写成void (__decel *p[])();
而标准规范用 __stdcall前缀。 也可以用宏CALLBACK,这也就是著名的回调
函数了。
使用CALLBACK的另一个好处就是呼叫函数(caller)不需要具体关心被叫函数(callee)是什么而直接呼叫。例如我们要写一个排序
函数。可以用各种不同算法。如冒泡法。
void CALLBACK BubbleSort(int *pStart, int *pEnd);
也可以用quick sort
void CALLBACK QuickSort(int *pStart, int *pEnd);
那么呼叫方只需要定义一个指向这种格式的
函数指针:
void (CALLBACK *p)(int*, int*),然后让p指向想用的
函数就可以了。
这里只对int类型排序,实际上这种排序函数可以再叫一个CALLBACK函数来决定排序规则。以使算法可以应用到各种不同类型的变量以及不同的排序规则中。在各算法书上都有介绍。如果大家有兴趣,我可以写一下这个排序
函数。
另一个典型的例子是MFC中Timer使用的CALLBACK函数,每当Timer Exprie的时候会去叫这个
函数,根据返回值决定下一个动作。
C++中的
函数指针与C的不同
class C
{
public:
bool test();
}
这里指向print的
指针不是bool *p(),而是bool (C::*p)();
呼叫这个
函数的时候这样写:
C c, *pc=&c;
bool (C::*p)() = &C::test;
c.*p();
或者 pc->*p();
赋值那行bool (C::*p)() = &C::test;在VS2003里右边可以省去 C::,到了VS2005语法更严格了,被禁止了。这里的成员函数
指针对非静态函数有效。静态
函数不依赖于任何object,它的表示方法和C的一样。
对于非静态成员
函数的指针的继承关系是这样的:upcast合法,downcast不合法。这样的到的
指针永远是安全的。
非静态成员函数
指针在实际程序中的应用很多。一个典型的例子是用来写state machine(状态机器?)。例如程序在控制一个机器人的初始化阶段。整个初始化需要三个函数:1。初始化机器人的身子,2。初始化机器的左手,3。初始化机器人的右手。这样我们在state machine中用两个成员
函数指针分别指向当前的状态和下一个状态 bool (CStateMachine::*m_pCurrentState), bool (CStateMachine::*m_pNextState)。。
一开始永远叫Start()
CStateMachine::CStateMachine
{
m_pCurrentState = CStateMachine::Start;
}
然后在每一个State里面管理状态变化:
bool CStateMachine::Start()
{
.....
m_pNextState = CStateMachine::InitializeLeftHand();
}
bool CStateMachine::InitializeLeftHand()
{
....
m_pNextState = CStateMachine::InitializeRightHand();
}
bool CStateMachine::InitializeRightHand()
{
....
m_pNextState = NULL;
}
这样很清晰的标志了整个初始化的过程。当然这个过程也可以用很土的程序实现,设一个flag,然后把flag于
函数一一对应。但那样作出来的程序不易懂,同时增加新状态的时候不好维护。
对于CStateMachine的核心部份可以这样控制:对于任何一步操作,如果
函数返回true表示成功,执行下一步
(this->*(m_pCurrentState = m_pNextState))()。如果失败则报错,同时让用户选择重试(Retry)还是放弃(Abort)还是忽略(Ignor)。
如果Abort则结束StateMachine,
如果Retry则再次叫当前
函数this->*m_pCurrentState();
如果Ignor则忽略当前错误继续下一步。this->*(m_pCurrentState = m_pNextState)();
当没有下一个状态的时候StateMachine结束。 (m_pNextState == NULL)
这是标准工业中的用法,大家不妨看一看,写成一个标准的class。这将是个很有用的练习。
分享到:
相关推荐
C/C++ 函数指针的意义,函数指针的用法
c++数组指针函数等关键内容讲解 c++数组指针函数等关键内容讲解 c++数组指针函数等关键内容讲解
里面包含: 普通函数指针,同一个类函数指针,不同类的函数指针的使用。
C#调用C++DLL,C++DLL中的函数参数包含指针。 绝对可用。
c++的指针特性学习之函数指针,代码中给出了函数指针的声明方式和使用方式,供大家使用函数指针参考
1.普通函数指针指向普通函数 2.普通函数指向非静态成员函数 3. 类外部的 类函数指针 指向普通函数 4. 类外部的 类函数指针 指向成员函数 5. 类内部的 函数指针 指向成员函数 (类似于第2条) 6. 类内部的 函数指针 ...
指针 不仅可以只想变量 常量 数组 还可以指向函数 。 本资源利用函数指针调用 求和函数
关于函数指针的理解,是C++中的一个知识点 初学者很容易范一些错误。 本文给了一个解释。
c++中的函数指针介绍,c++入门知识,详细的介绍了函数指针的定义方法和用法
C++编程语言中函数指针常见用法:函数调用及回调函数中的使用。
本文实例分析了C++中回调函数(CallBack)的用法。分享给大家供大家参考。具体分析如下: 如果试图直接使用C++的成员函数作为回调函数将发生错误,甚至编译就不能通过。 其错误是普通的C++成员函数都隐含了一个传递...
在C++中,通过多维数据的指针作为函数参数传递源程序
在C#中,为了提供类似C++中函数指针的功能,微软提出了委托和事件的概念。这里有一个很奇怪的事情,那就是当牵涉到指针是,对于初学者而言,似乎很费解。鄙人对于C#中的委托和事件有一些见解,希望对那些要了解委托...
关于指针函数、函数指针等诸多易混淆一错用的辨析
这篇文档介绍了c++中函数指针的如用方法,另外对typedef的用法进行介绍,希望对你能有帮助。。
定义指向函数的指针,这种指针可以被赋值...
里面包含函数和指针概念的详细讲解,北大名师所做。希望能够对学C/C++的同学有所帮助。
指针函数和函数指针是C语言里两个比较绕的概念。但是不仅面试题爱考,实际应用中也比较广泛。很多人因为搞不清这两个概念,干脆就避而远之,我刚接触C语言的时候对这两个概念也比较模糊,特别是当指针函数、函数指针...
英文的。 C/C++ 函数指针教程 C/C++ 函数指针教程 C/C++ 函数指针教程
C++大学课本,函数指针调用具体使用案例详细讲解