什么是C ++代表?
C ++中委托的一般概念是什么? 他们是什么,他们是如何使用,他们用于什么?
我想首先以“黑匣子”的方式来了解它们,但是关于这些事情的一些信息也会很棒。
这不是最纯粹或最干净的C ++,但我注意到我工作的代码库有丰富的。 我希望能够理解它们,所以我可以使用它们,而不必钻研可怕的嵌套模板可怕。
这两个代码项目文章解释我的意思,但不是特别简洁:
-
成员函数指针和最快可能的C ++代表
-
不可能的快速C ++代表
你有一个令人难以置信的数量的select来实现C ++中的代表。 这是我想到的那些。
选项1:仿函数:
函数对象可以通过实现operator()
来创build
struct Functor { // Normal class/struct members int operator()(double d) // Arbitrary return types and parameter list { return (int) d + 1; } }; // Use: Functor f; int i = f(3.14);
选项2:lambdaexpression式(仅限C ++ 11 )
// Syntax is roughly: [capture](parameter list) -> return type {block} // Some shortcuts exist auto func = [](int i) -> double { return 2*i/1.15; }; double d = func(1);
选项3:函数指针
int f(double d) { ... } typedef int (*MyFuncT) (double d); MyFuncT fp = &f; int a = fp(3.14);
选项4:指向成员函数的指针 (最快解决scheme)
请参阅快速C ++委托 (在代码项目上 )。
struct DelegateList { int f1(double d) { } int f2(double d) { } }; typedef int (DelegateList::* DelegateType)(double d); DelegateType d = &DelegateList::f1; DelegateList list; int a = (list.*d)(3.14);
选项5: std :: function
(或者如果你的标准库不支持boost::function
)。 速度较慢,但最为灵活。
#include <functional> std::function<int(double)> f = [can be set to about anything in this answer] // Usually more useful as a parameter to another functions
选项6:绑定(使用std :: bind )
允许预先设置一些参数,方便调用成员函数。
struct MyClass { int DoStuff(double d); // actually a DoStuff(MyClass* this, double d) }; std::function<int(double d)> f = std::bind(&MyClass::DoStuff, this, std::placeholders::_1); // auto f = std::bind(...); in C++11
选项7:模板
只要符合参数列表就接受任何东西。
template <class FunctionT> int DoSomething(FunctionT func) { return func(3.14); }
委托是一个包装对象实例的指针或引用的类,该对象的类的成员方法将在该对象实例上调用,并提供触发该对象的方法。
这是一个例子:
template <class T> class CCallback { public: typedef void (T::*fn)( int anArg ); CCallback(T& trg, fn op) : m_rTarget(trg) , m_Operation(op) { } void Execute( int in ) { (m_rTarget.*m_Operation)( in ); } private: CCallback(); CCallback( const CCallback& ); T& m_rTarget; fn m_Operation; }; class A { public: virtual void Fn( int i ) { } }; int main( int /*argc*/, char * /*argv*/ ) { A a; CCallback<A> cbk( a, &A::Fn ); cbk.Execute( 3 ); }
对C ++委托实现的需求是对C ++社区持久的尴尬。 每个C ++程序员都会喜欢拥有它们,所以最终他们会使用它们,尽pipe事实如下:
-
std::function()
使用堆操作(对于严重的embedded式编程而言是无法实现的)。 -
所有其他的实现方式都是对可移植性或标准符合性做出更大或更小的让步(请通过检查这里和代码项目中的各种委托实现进行validation)。 我还没有看到一个不使用野生reinterpret_casts的实现,嵌套类“原型”,希望产生与用户传入的函数指针大小相同的函数指针,编译器技巧,如第一次正向声明,然后typedef然后再声明,这个时候inheritance了另一个类或类似的黑幕技术。 虽然这对构build它的实现者来说是一个伟大的成就,但它仍然是C ++如何演化的一个可悲的挑战。
-
目前只有很less人指出,现在超过3个C ++标准版本,代表没有得到妥善解决。 (或缺乏允许直接的委托实现的语言function。)
-
随着C ++ 11 lambda函数由标准定义(每个lambda具有匿名,不同types)的方式,这种情况在一些使用情况下只有改进。 但是对于在(DLL)库API中使用委托的用例, 单独的lambda仍然不可用。 这里常见的技术是首先将lambda打包到std :: function中,然后通过API传递它。
很简单,委托提供了函数指针应该如何工作的function。 C ++中的函数指针有很多限制。 一个委托使用一些幕后的模板不愉快来创build一个模板类的函数指针types的东西,以你想要的方式工作。
即 – 你可以设置他们指向一个给定的function,你可以把它们传给他们,随时随地给他们打电话。
这里有一些很好的例子:
这里没有提到的C ++委托的选项是使用函数ptr和上下文参数来执行C风格。 这可能是许多要求这个问题试图避免的相同模式。 但是,模式是便携的,高效的,并且可用于embedded式和内核代码。
class SomeClass { in someMember; int SomeFunc( int); static void EventFunc( void* this__, int a, int b, int c) { SomeClass* this_ = static_cast< SomeClass*>( this__); this_->SomeFunc( a ); this_->someMember = b + c; } }; void ScheduleEvent( void (*delegateFunc)( void*, int, int, int), void* delegateContext); ... SomeClass* someObject = new SomeObject(); ... ScheduleEvent( SomeClass::EventFunc, someObject); ...
标准C ++中的一个函数对象的Windows运行时等价物。 可以使用整个函数作为参数(实际上是一个函数指针)。 它主要与事件一起使用。 代表表示事件处理程序完成的合同。 它便于函数指针如何工作。