回调例程似乎是迄今为止提出的最常见的场景.但是,还有很多其他......
有限状态机,其中(多维)数组的元素指示处理/处理下一状态的例程.这使FSM的定义保持在一个位置(数组).
可以使用函数指针来启用功能和禁用功能.您可能具有要启用或禁用的功能,以执行类似但不同的功能.不使用if-else构造测试变量来填充和混乱代码,您可以对其进行编码以使其使用函数指针,然后您可以通过更改/分配函数指针来启用/禁用功能.如果您添加新变体,则无需追踪所有if-else或switch案例(并且可能缺少一个); 相反,您只需更新您的函数指针以启用新功能,或禁用旧功能.
减少代码混乱 我在前面的例子中触及了这一点.例如......
switch (a) {
case 0:
func0();
break;
case 1:
func1();
break;
case 2:
func2();
break;
case 3:
func3();
break;
default:
funcX();
break;
}
Run Code Online (Sandbox Code Playgroud)
可以简化为......
/* This declaration may be off a little, but I am after the essence of the idea */
void (*funcArray)(void)[] = {func0, func1, func2, func3, funcX};
... appropriate bounds checking on 'a' ...
funcArray[a]();
Run Code Online (Sandbox Code Playgroud)
还有更多.希望这可以帮助.
作为一个非常有用的应用程序,我首先想到的是一个按钮.请使用以下代码:
int buttonID = CreateButton ("Click Me!", 100, 100, 200, 100, onClick);
Run Code Online (Sandbox Code Playgroud)
这将在(100,100)处创建一个宽度为200且高度为100的按钮.每次单击它时,都会调用onClick.
我在个人Windows API包装器中使用类似的东西.它使创建按钮等变得更加容易.
函数指针有两个主要用途:
GetProcAddress,dlsym或类似的,其采取的功能标识符作为名称,并返回一个函数指针.对于像OpenGL这样的API来说绝对至关重要.在大多数情况下,它本质上是执行依赖倒置的C 方式。维基百科文章指出:
A. 高层模块不应该依赖于低层模块。两者都应该依赖于抽象。B. 抽象不应依赖于细节。细节应该取决于抽象。
经典示例的qsort意思是,高级排序函数不依赖于要排序的数据的类型、大小或比较方法。因此,如果您有qsort()一个整数数组,则详细信息是sizeof(int)您的比较实现。抽象是任意大小元素的数组和比较该类型元素的函数。
另请参阅:控制反转。
我很惊讶没有人提到pthread_create()这个例子。
我能想到的唯一不能概括为依赖倒置的常见用途是对不可切换的数据类型实现类似开关的流控制。例如,如果您曾经想要打开字符串,请创建将排序字符串键映射到函数指针的数组,并进行二分搜索。它不像 switch 那样是 O(1),但比盲目地在一个大的 if-else 中执行 strcmp() 直到找到匹配要好。但也许并不比标记字符串并使用实际的开关更好。