函数指针的进化论(1)

函数指针 (function pointer) 是传统 C 语言中少数的动态机制,但是近来许多语言都不再支持函数指针 (包括 Java 和 C#),而改用其它机制来代替。本文章简单扼要地说明,多态 (polymorphism)、反射 (reflection)、委托 (delegate) 如何取代函数指针。


http://www.microsoft.com/taiwan/msdn/columns/donet/functionpointer_1.htm

http://www.microsoft.com/taiwan/msdn/columns/donet/functionpointer_2.htm

摘要

函数指针 (function pointer) 是传统 C 语言中少数的动态机制,但是近来许多语言都不再支持函数指针 (包括 Java C#),而改用其它机制来代替。本文章简单扼要地说明,多态 (polymorphism)、反射 (reflection)、委托 (delegate) 如何取代函数指针。

函数指针(function pointer) 是一种「指向函数的指针」,和一般指向资料的指针不同。凡是研究过许多系统原代码 (例如:Linux KernelBorland OWL) 的人,对于函数指针应该都不陌生,因为多数低阶系统都使用 C 语言编写,而函数指针是传统C语言中少数的动态机制,有许多不可取代的地方,所以这些 C 原代码中到处可见函数指针。

透过一个实际的范例,来了解何谓函数指针:

// FncPtr.cpp
#include 
using std::cin;
using std::cout;
using std::endl;
// 声明 Fnc1(), Fun2(), Twice()
float Fnc1(int);
float Fnc2(int);
double Twice(float (*)(int), int);
// 主程序
int main() {
  int A = 3;
  int B = 5;
  count << "Twice(Fnc1, A)的值为: "
            << Twice(Fnc1, A) << endl;
  count << "Twice(Fnc2, B)的值为: "
            << Twice(Fnc2, B) << endl;
}
float Fnc1(int N) {
  return float (N*N);
}
float Fnc2(int N) {
  return float (N*N*N);
}
double Twice(float (*pF)(int), int N) {
  return 2.0 * double(pF(N));
}

执行结果:

Twice(Fnc1, A)的值为:18
Twice(Fnc2, B)的值为:250

此例中,pF 即为函数指针,而函数名称本身 (Fun1 Fun2) 是常数的函数指针。通过函数指针,函数被资料化了 (变成指针),如此一来函数也可以被传递、被纪录,所以 Fnc1 Fnc2 可以被当成参数,传进 Twice() 中。

一旦函数可以被传递、被纪录,这开启了许多可能性,产生许多有趣的应用,特别是下列三者:

·                 多态 (polymorphism):稍后再说明。

·                 多线程 (multithreading):将函数指针传进负责建立多线程的 API 中:例如 Win32 CreateThread(...pF...)

·                 回调 (call-back):所谓的回调机制就是:「当发生某事件时,自动呼叫某段程序代码」,Charles Petzold 称此为「Dont Call Me, I'll Call You」。事件驱动 (event-driven) 的系统经常透过函数指针来实现回调机制,例如 Win32 WinProc 其实就是一种回调,用来处理窗口的讯息。

函数指针的致命缺点是:无法对参数 (parameter) 和返回值 (return value) 的型态进行检查,因为函数已经退化成指针,指针是不带有这些型态信息的。少了型态检查,当参数或返回值不一致时,会造成严重的错误。编译器和虚拟机器 (VM) 并不会帮我们找出函数指针这样的致命错误。所以,许多新的程序语言不支持函数指针,而改用其它方式。

多态

多态的实现方式很复杂,大致上是编译器或 VM 在数据结构内加入一个资料指针,此指针通常称为 vptr,是 Virtual Table Pointer 的意思。vptr 指向一个 Virtual Table,此 Virtual Table 是一个数组 (array),由许多函数指针所组成,每个函数指针各自指向一个函数的地址。如图 1 所示。

 函数指针

(未完待续)

作者:蔡學鏞   更新日期:2004-11-07
来源:MSDN台湾   浏览次数:

相关文章

相关评论   发表评论