函数引用
所以我只是在使用函数指针,我记得你可以这样做:
void Foo() { } int main() { void(& func)() = Foo; func(); //::Foo(); }
显而易见的优点是引用引用了有效的对象(除非它们被滥用)或者在这种情况下的函数。
显而易见的缺点是你不能存储一个引用数组,并且不能将它们用于成员函数指针(至less据我所知)。
我的问题:有没有人使用它们(即函数引用 , 而不是函数指针),如果是这样,在什么情况下,你发现他们有用/有帮助?
唯一能看到它们是有用的地方是在使用条件编译时绑定对某个函数的引用。
我已经使用它们,通过以类似于战略模式的方式将它们传递给构造函数来为类添加自定义
我认为你的例子用法是相当不错的。 因为如果你要使用一个普通的函数指针,然后你应用这个地址的运算符,你会得到函数指针的地址。 使用对函数的引用将做预期的事情,因为它返回一个指向函数本身的指针。
我也想不到很多例子。 保持函数引用,正如你所指出的,有一些丑陋的后果。 另一个可能不希望出现的后果是,如果作为类成员保存,如果您不写入自己的operator =,并且不要尝试重新分配函数引用,则对象将是不可分配的。
我认为函数引用的大多数用法是隐含的,就像大多数数组引用的用法一样 – 尽pipe如此,当您通过引用来接受参数时:
template<typename T> void do_something(T const& t) { ... }
尽pipe通过引用来接受数组具有不丢失其大小信息的优点,但通过引用明确地接受函数似乎没有优势(至less据我所知)。 我认为,函数引用的存在很大程度上是由作为某个对象或函数的别名名称的理想主义视图,以及允许将函数传递给通过引用接受其参数的模板的事实来certificate的。
我可能会避免使用它们,如果我不会不可避免地需要它们的话。 常量函数指针还提供了不可重定位的可调参数,当其他程序员可能不太熟悉这种语言环境时,可能会避免混淆读取代码。 值得注意的是,Vandervoorde&Josuttis也build议避免他们减less混淆(在他们的书“C ++模板 – 完整指南”中)。
与函数指针不同,函数引用使得从无效源创build它们变得更加困难。 如果你正在做一个C库的包装器,这是非常有用的 – 如果lbrary要求传入的指针不能为NULL,那么C ++代码可以通过引用接受一个callback函数并将指针传递给C库。
这也是一个方便的方法,特别是在C ++ 11中使用新的auto关键字:
#include <iostream> #include <typeinfo> void f(int i, char c) { std::cout << i << ' ' << c << std::endl; } int main() { std::cout << typeid(f).name() << std::endl; //FvicE f(0, '1'); void (*pf)(int, char) (&f); //ugly std::cout << typeid(pf).name() << std::endl; //PFvicE (*pf)(2, '3'); pf(4, '5'); //works, but I don't recommend it void (&rf)(int, char) (f); //still ugly std::cout << typeid(rf).name() << std::endl; //FvicE rf(6, '7'); auto &af (f); //pretty, but only works in C++11 std::cout << typeid(af).name() << std::endl; //FvicE, same as above af(8, '9'); }
我已经在插件系统中使用它们,插件DLL可以在运行时加载/卸载。 我会查找每个DLL中的已知符号,并将它们转换为函数指针。
除了用作策略(正如罗伯特·古尔德所指出的那样)之外,我在(模板)元编程的入口点频繁地使用它们。 函数引用可以很容易地被模板参数拾取; 从这一点上它可以通过几个层(元编程)模板。 当然,这也适用于函数指针,但引用是别名 ,因此更清楚地传达了意图。
举一个例子:当为应用程序编写通用命令调度系统时,需要将许多不同的操作作为命令来公布。 我们可以使用一个简单的“构build函数”作为客户端代码的前端。 在这个幕后,这个构造器函数将实际的函数签名作为模板参数,通过模板元编程(metaprogramming)得到实际的参数和返回值types,并可能select合适的专门用来存储“纪念品”和“回收函子”。 这些仿函数可以作为函数指针在内部存储,也可以使用boost或tr1或C ++ 11函数对象。 这样,就可以build立一个types安全的命令调用和“撤销”系统。
我参与了一个项目,该项目旨在使用函数指针和结构来实现C中的Object对象。 由于function可以被replace,他们可以实现一种inheritance系统。 幸运的是,这种努力打破了。 虽然这个任务很有意思,但是这个项目并不是一个好主意(对于生产中的任何东西都不是个好主意)。
如前所述,我还使用了基于DLL的可插拔模块系统的函数指针。