C++ 函数指针的意义是什么?
我很难看到函数指针的实用性。我想它在某些情况下可能有用(毕竟它们是存在的),但我想不出使用函数指针更好或不可避免的情况 您能给出一些函数指针的良好使用示例(在C或C++中)吗?示例:C++ 函数指针的意义是什么?,c++,c,function,pointers,c++-faq,C++,C,Function,Pointers,C++ Faq,我很难看到函数指针的实用性。我想它在某些情况下可能有用(毕竟它们是存在的),但我想不出使用函数指针更好或不可避免的情况 您能给出一些函数指针的良好使用示例(在C或C++中)吗?示例: 自定义排序/搜索 不同的 模式(如策略、观察者) 回调 函数指针可以在C语言中用来创建一个接口来进行编程。根据运行时需要的特定功能,可以为函数指针指定不同的实现。在C中,经典用法是,其中第四个参数是指向用于在排序中执行排序的函数的指针。在C++中,人们倾向于使用函数(类似于函数的对象)来处理这种事情。 < P>函数
函数指针可以在C语言中用来创建一个接口来进行编程。根据运行时需要的特定功能,可以为函数指针指定不同的实现。在C中,经典用法是,其中第四个参数是指向用于在排序中执行排序的函数的指针。在C++中,人们倾向于使用函数(类似于函数的对象)来处理这种事情。 < P>函数指针有用性的“经典”例子是C库<代码> qSoTo()/Cuff>函数,它实现了快速排序。为了对用户可能提出的任何和所有数据结构具有通用性,它需要两个指向可排序数据的void指针和一个指向知道如何比较这些数据结构的两个元素的函数的指针。这允许我们为作业创建我们的选择函数,事实上甚至允许在运行时选择比较函数,例如用于升序或降序排序。大多数示例归结为回调:调用函数
f()
传递另一个函数的地址g()
,以及f()
为某些特定任务调用g()。如果您将f()
的地址改为h()
,则f()
将调用h()
基本上,这是一种将函数参数化的方法:它的某些行为不是硬编码到f()
,而是硬编码到回调函数中。调用方可以通过传递不同的回调函数使f()
的行为不同。经典的是C标准库中的qsort()
,它将排序标准作为指向比较函数的指针
在C++中,这通常是使用<强>函数对象< /St>(也称为函子)来完成的。这些对象重载函数调用操作符,因此您可以像调用函数一样调用它们。例如:
class functor {
public:
void operator()(int i) {std::cout << "the answer is: " << i << '\n';}
};
functor f;
f(42);
类函子{
公众:
void操作符()(inti){std::cout同意上述所有条件,加上。。。。
当您在运行时动态加载dll时,您将需要函数指针来调用函数。这里我将与当前相反
在C语言中,函数指针是实现定制的唯一方法,因为没有OO
在C++中,可以使用函数指针或函数(函数对象)来获得相同的结果。
与原始函数指针相比,函子有许多优点,这是由于它们的对象性质,尤其是:
- 它们可能会出现
运算符()的多个重载
- 它们可以具有对现有变量的状态/引用
- 它们可以当场构建(
lambda
和bind
)
我个人更喜欢函子而不是函数指针(尽管有样板代码),主要是因为函数指针的语法很容易变得复杂(从以下方面):
我唯一一次看到函数指针在函数无法使用的地方使用是在Boost.Spirit中。它们完全滥用语法,将任意数量的参数作为单个模板参数传递
typedef SpecialClass<float(float,float)> class_type;
typedef特殊类\u类型;
但由于变量模板和lambdas是在拐角处,我不确定我们现在会用函数C++指针来表示长时间。
嗯,我一般在(专业)中使用它们(参见)。
跳转表通常(但不是唯一)用于使它们成为数据驱动的。而不是嵌套的开关/大小写
switch (state)
case A:
switch (event):
case e1: ....
case e2: ....
case B:
switch (event):
case e3: ....
case e1: ....
您可以创建一个2d函数指针数组,只需调用handleEvent[state][event]
我最近使用函数指针创建了一个抽象层
我有一个在嵌入式系统上运行的纯C语言程序。它支持多种硬件变体。根据我运行的硬件,它需要调用某些函数的不同版本
在初始化时,程序计算出它运行在什么硬件上,并填充函数指针。程序中的所有高级例程只调用指针引用的函数。我可以添加对新硬件变体的支持,而无需接触高级例程
我曾经使用switch/case语句来选择合适的函数版本,但随着程序支持越来越多的硬件变体,这变得不切实际。我不得不到处添加case语句
我还尝试了中间函数层来确定要使用哪一个函数,但没有多大帮助。每当我们添加一个新的变量时,我仍然必须在多个地方更新case语句。有了函数指针,我只需要更改初始化函数。我广泛使用函数指针来模拟微处理器具有1字节操作码的OR。256个函数指针数组是实现这一点的自然方式。我的主要用途是回调:当需要保存有关函数的信息时,请稍后调用
// user placed a bomb
Bomb* bomb = new Bomb()
make callback( function=bomb.explode, time=5 seconds ) ;
// IN the main loop:
foreach callback in callbacks
if callback.timeToRun
callback.function()
假设您正在编写Bomberman。在投弹者投下炸弹5秒后,炸弹应该会爆炸(调用explode()
函数)
现在有两种方法,一种是“探测”屏幕上的所有炸弹,看看它们是否准备在主回路中爆炸
foreach bomb in game
if bomb.boomtime()
bomb.explode()
另一种方法是将回调函数附加到时钟系统。当放置炸弹时,您可以添加回调函数,使其在时间合适时调用bomb.explode()
foreach bomb in game
if bomb.boomtime()
bomb.explode()
// user placed a bomb
Bomb* bomb = new Bomb()
make callback( function=bomb.explode, time=5 seconds ) ;
// IN the main loop:
foreach callback in callbacks
if callback.timeToRun
callback.function()
my_function(my_arg);
(&my_function)(my_arg);
(*my_function)(my_arg);
(**my_function)(my_arg);
(&**my_function)(my_arg);
(***my_function)(my_arg);
#include<iostream>
#include<map>
using namespace std;
//typedef map<string, int (*)(int x, int y) > funMap;
#define funMap map<string, int (*)(int, int)>
funMap objFunMap;
int Add(int x, int y)
{
return x+y;
}
int Sub(int x, int y)
{
return x-y;
}
int Multi(int x, int y)
{
return x*y;
}
void initializeFunc()
{
objFunMap["Add"]=Add;
objFunMap["Sub"]=Sub;
objFunMap["Multi"]=Multi;
}
int main()
{
initializeFunc();
while(1)
{
string func;
cout<<"Enter your choice( 1. Add 2. Sub 3. Multi) : ";
int no, a, b;
cin>>no;
if(no==1)
func = "Add";
else if(no==2)
func = "Sub";
else if(no==3)
func = "Multi";
else
break;
cout<<"\nEnter 2 no :";
cin>>a>>b;
//function is called using function pointer based on user input
//If user input is 2, and a=10, b=3 then below line will expand as "objFuncMap["Sub"](10, 3)"
int ret = objFunMap[func](a, b);
cout<<ret<<endl;
}
return 0;
}
Enter your choice( 1. Add 2. Sub 3. Multi) : 1
Enter 2 no :2 4
6
Enter your choice( 1. Add 2. Sub 3. Multi) : 2
Enter 2 no : 10 3
7
Enter your choice( 1. Add 2. Sub 3. Multi) : 3
Enter 2 no : 3 6
18
struct Base;
struct Base_vtable {
void (*destruct)(struct Base* me);
};
struct Base {
struct Base_vtable* vtable;
};
struct Derived;
struct Derived_vtable {
struct Base_vtable;
void (*frobnicate)(struct Derived* me);
};
struct Derived {
struct Base;
int bar, baz;
}
switch(me->type) {
case TYPE_BASE: base_implementation(); break;
case TYPE_DERIVED1: derived1_implementation(); break;
case TYPE_DERIVED2: derived2_implementation(); break;
case TYPE_DERIVED3: derived3_implementation(); break;
}