3 回答
TA贡献1887条经验 获得超5个赞
您可以通过多种选择来实现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);
选项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);
选项3:函数指针
int f(double d) { ... }
typedef int (*MyFuncT) (double d);
MyFuncT fp = &f;
int a = fp(3.14);
选项4:指向成员函数的指针(最快的解决方案)
请参见Fast C ++ Delegate(在The Code Project上)。
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);
}
TA贡献1830条经验 获得超3个赞
委托是一个类,它包装指向对象实例的指针或引用,该对象实例在该对象实例上要被调用的成员方法,并提供触发该调用的方法。
这是一个例子:
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 );
}
TA贡献1836条经验 获得超5个赞
对C ++委托实现的需要是对C ++社区的长期困扰。每个C ++程序员都希望拥有它们,因此尽管存在以下事实,他们还是最终使用了它们:
std::function()
使用堆操作(对于严重的嵌入式编程是无法实现的)。所有其他实现都在或多或少程度上对可移植性或标准一致性做出了让步(请通过在此处和在代码项目上检查各种委托实现进行验证)。我还没有看到一个不使用野生的reinterpret_casts的实现,嵌套类“原型”希望产生与用户传递的函数指针大小相同的函数指针,编译器的技巧如第一个前向声明,然后是typedef然后再声明,这次是从另一个班级或类似的黑幕技术继承下来的。虽然这对于实现此目标的实现者来说是一项巨大的成就,但对于C ++的发展仍然是一个可悲的见证。
很少有人指出,现在超过3个C ++标准修订版,未正确处理委托。(或者缺少允许直接实现委托实现的语言功能。)
通过标准定义C ++ 11 lambda函数的方式(每个lambda具有匿名的不同类型),这种情况仅在某些用例中得到了改善。但是对于在(DLL)库API中使用委托的用例,仅 lambda 仍然不可用。此处的常用技术是先将lambda打包到std :: function中,然后将其传递给API。
- 3 回答
- 0 关注
- 641 浏览
添加回答
举报