什么是 C++ 委托?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9568150/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 12:59:29  来源:igfitidea点击:

What is a C++ delegate?

c++delegatesdelegation

提问by SirYakalot

What is the general idea of a delegate in C++? What are they, how are they used and what are they used for?

C++ 中委托的一般概念是什么?它们是什么,它们是如何使用的以及它们的用途是什么?

I'd like to first learn about them in a 'black box' way, but a bit of information on the guts of these things would be great too.

我想首先以“黑匣子”的方式了解它们,但一些关于这些东西的胆量的信息也会很棒。

This is not C++ at its purest or cleanest, but I notice that the codebase where I work has them in abundance. I'm hoping to understand them enough, so I can just use them and not have to delve into the horrible nested template awfulness.

这不是最纯粹或最干净的 C++,但我注意到我工作的代码库有很多。我希望对它们有足够的了解,所以我可以只使用它们而不必深入研究可怕的嵌套模板的可怕之处。

These two The Code Projectarticles explain what I mean but not particularly succinctly:

这两篇The Code Project文章解释了我的意思,但不是特别简洁:

回答by J.N.

You have an incredible number of choices to achieve delegates in C++. Here are the ones that came to my mind.

在 C++ 中实现委托的选择数量令人难以置信。以下是我想到的那些。



Option 1 : functors:

选项 1:函子:

A function object may be created by implementing operator()

一个函数对象可以通过实现来创建 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);


Option 2: lambda expressions (C++11only)

选项 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);


Option 3: function pointers

选项 3:函数指针

int f(double d) { ... }
typedef int (*MyFuncT) (double d);
MyFuncT fp = &f;
int a = fp(3.14);


Option 4: pointer to member functions(fastest solution)

选项 4:指向成员函数的指针(最快的解决方案)

See Fast C++ Delegate(on The Code Project).

请参阅Fast C++ Delegate(在代码项目上)。

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);


Option 5: std::function

选项 5:std::function

(or boost::functionif your standard library doesn't support it). It is slower, but it is the most flexible.

(或者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


Option 6: binding (using std::bind)

选项 6:绑定(使用std::bind

Allows setting some parameters in advance, convenient to call a member function for instance.

允许提前设置一些参数,例如方便调用成员函数。

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


Option 7: templates

选项 7:模板

Accept anything as long as it matches the argument list.

只要与参数列表匹配,就接受任何内容。

template <class FunctionT>
int DoSomething(FunctionT func)
{
    return func(3.14);
}

回答by Grimm The Opiner

A delegate is a class that wraps a pointer or reference to an object instance, a member method of that object's class to be called on that object instance, and provides a method to trigger that call.

委托是包装对象实例的指针或引用的类、要在该对象实例上调用的该对象类的成员方法,并提供触发该调用的方法。

Here's an example:

下面是一个例子:

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 );
}

回答by BitTickler

The need for C++ delegate implementations are a long lasting embarassment to the C++ community. Every C++ programmer would love to have them, so they eventually use them despite the facts that:

对 C++ 委托实现的需求是 C++ 社区的长期尴尬。每个 C++ 程序员都希望拥有它们,因此尽管有以下事实,他们最终还是会使用它们:

  1. std::function()uses heap operations (and is out of reach for serious embedded programming).

  2. All other implementations make concessions towards either portability or standard conformity to larger or lesser degrees (please verify by inspecting the various delegate implementations here and on codeproject). I have yet to see an implementation which does not use wild reinterpret_casts, Nested class "prototypes" which hopefully produce function pointers of the same size as the one passed in by the user, compiler tricks like first forward declare, then typedef then declare again, this time inheriting from another class or similar shady techniques. While it is a great accomplishment for the implementers who built that, it is still a sad testimoney on how C++ evolves.

  3. Only rarely is it pointed out, that now over 3 C++ standard revisions, delegates were not properly addressed. (Or the lack of language features which allow for straightforward delegate implementations.)

  4. With the way C++11 lambda functions are defined by the standard (each lambda has anonymous, different type), the situation has only improved in some use cases. But for the use case of using delegates in (DLL) library APIs, lambdas aloneare still not usable. The common technique here, is to first pack the lambda into a std::function and then pass it across the API.

  1. std::function()使用堆操作(对于严肃的嵌入式编程来说是遥不可及的)。

  2. 所有其他实现在可移植性或标准一致性方面做出更大或更小的让步(请通过检查此处和 codeproject 上的各种委托实现来验证)。我还没有看到一个不使用wild reinterpret_casts的实现,嵌套类“原型”,它希望产生与用户传入的相同大小的函数指针,编译器技巧,如先前向声明,然后typedef然后再次声明,这次是从另一个类或类似的黑幕技术继承。虽然对于构建它的实现者来说这是一项伟大的成就,但它仍然是 C++ 如何发展的悲惨见证。

  3. 很少有人指出,现在超过 3 个 C++ 标准修订版,没有正确解决代表问题。(或者缺少允许直接委托实现的语言特性。)

  4. 随着标准定义 C++11 lambda 函数的方式(每个 lambda 都有匿名的、不同的类型),情况只在某些用例中有所改善。但是对于在 (DLL) 库 API 中使用委托的用例,单独的lambda仍然不可用。这里的常用技术是首先将 lambda 打包到 std::function 中,然后通过 API 传递它。

回答by SirYakalot

Very simply, a delegate provides functionality for how a function pointer SHOULD work. There are many limitations of function pointers in C++. A delegate uses some behind-the-scenes template nastyness to create a template-class function-pointer-type-thing that works in the way you might want it to.

很简单,委托提供了函数指针应该如何工作的功能。C++ 中函数指针有很多限制。委托使用一些幕后模板讨厌来创建模板类函数指针类型的东西,它以您可能希望的方式工作。

ie - you can set them to point at a given function and you can pass them around and call them whenever and wherever you like.

即 - 您可以将它们设置为指向给定的函数,您可以传递它们并随时随地调用它们。

There are some very good examples here:

这里有一些很好的例子:

回答by Joe

An option for delegates in C++ that is not otherwise mentioned here is to do it C style using a function ptr and a context argument. This is probably the same pattern that many asking this question are trying to avoid. But, the pattern is portable, efficient, and is usable in embedded and kernel code.

此处未提及的 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);
    ...

回答by nmserve

Windows Runtime equivalent of a function object in standard C++. One can use the whole function as a parameter (actually that is a function pointer). It is mostly used in conjunction with events. The delegate represents a contract that event handlers much fulfill. It facilitate how a function pointer can work for.

Windows 运行时相当于标准 C++ 中的函数对象。可以将整个函数用作参数(实际上是函数指针)。它主要与事件结合使用。委托代表事件处理程序非常履行的契约。它促进了函数指针的工作方式。