J.N*_*.N. 162
您有很多选择来实现C++中的委托.以下是我想到的.
选项1:仿函数:
可以通过实现来创建功能对象 operator()
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);
Run Code Online (Sandbox Code Playgroud)
选项2:lambda表达式(仅限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);
Run Code Online (Sandbox Code Playgroud)
选项3:函数指针
int f(double d) { ... }
typedef int (*MyFuncT) (double d);
MyFuncT fp = &f;
int a = fp(3.14);
Run Code Online (Sandbox Code Playgroud)
选项4:指向成员函数的指针(最快的解决方案)
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);
Run Code Online (Sandbox Code Playgroud)
选项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
Run Code Online (Sandbox Code Playgroud)
选项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
Run Code Online (Sandbox Code Playgroud)
选项7:模板
只要它与参数列表匹配就接受任何内容.
template <class FunctionT>
int DoSomething(FunctionT func)
{
return func(3.14);
}
Run Code Online (Sandbox Code Playgroud)
Gri*_*ner 34
委托是一个包装对象实例的指针或引用的类,该对象实例上要调用的该对象的类的成员方法,并提供触发该调用的方法.
这是一个例子:
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 );
}
Run Code Online (Sandbox Code Playgroud)
Bit*_*ler 15
对C++委托实施的需求是对C++社区的持久尴尬.每个C++程序员都喜欢拥有它们,所以尽管事实如下:
std::function() 使用堆操作(并且对于严肃的嵌入式编程来说是遥不可及的).
所有其他实现都对可移植性或标准符合性做出更大或更小程度的让步(请通过检查此处和代码项目中的各种委托实现来验证).我还没有看到不使用野生reinterpret_casts,嵌套类"原型",这有望产生同样大小的一个用户传递的函数指针,编译器的技巧,比如第一向前声明的实现,那么的typedef然后再次申报,这次继承自另一个类或类似的阴暗技术.虽然对于构建它的实现者来说这是一个很大的成就,但对于C++如何发展仍然是一个悲伤的证据.
它很少被指出,现在超过3个C++标准版本,代表没有得到妥善解决.(或者缺乏允许直接委托实现的语言功能.)
通过标准定义C++ 11 lambda函数的方式(每个lambda具有匿名,不同类型),在某些用例中情况才得到改善.但是对于在(DLL)库API中使用委托的用例,单独使用lambdas 仍然无法使用.这里常见的技术是首先将lambda打包成std :: function,然后将其传递给API.
很简单,委托提供函数指针应该如何工作的功能.C++中的函数指针存在许多局限性.委托使用一些幕后模板讨厌来创建模板类函数 - 指针类型的东西,它以你可能想要的方式工作.
即 - 您可以将它们设置为指向给定的功能,您可以随时随地传递它们并随时随地调用它们.
这里有一些很好的例子:
此处未提及的 C++ 中委托的一个选项是使用函数 ptr 和上下文参数来实现 C 风格。这可能与许多提出此问题的人试图避免的模式相同。但是,该模式是可移植的、高效的,并且可用于嵌入式和内核代码。
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);
...
Run Code Online (Sandbox Code Playgroud)