Programing

C ++ 대리자는 무엇입니까?

lottogame 2020. 6. 24. 07:55
반응형

C ++ 대리자는 무엇입니까?


C ++에서 델리게이트의 일반적인 아이디어는 무엇입니까? 그들은 무엇이며 어떻게 사용되며 무엇을 위해 사용됩니까?

먼저 '블랙 박스'방식으로 그들에 대해 배우고 싶지만, 이런 것들의 내장에 대한 약간의 정보도 훌륭 할 것입니다.

이것은 C ++이 가장 순수하거나 깨끗하지 않지만, 내가 작업하는 코드베이스에 풍부함이 있음을 알았습니다. 나는 그것들을 충분히 이해하기를 바라고 있으므로 그냥 사용할 수 있으며 끔찍한 중첩 템플릿 끔찍함을 탐구 할 필요가 없습니다.

이 두 가지 코드 프로젝트 기사는 내가 의미하는 바를 간결하게 설명하지는 않습니다.


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 : 람다 식 ( 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를 참조하십시오 .

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 : 표준 :: 기능

(또는 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);
}

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

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:

  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 alone are still not usable. The common technique here, is to first pack the lambda into a std::function and then pass it across the API.


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.

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:


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.

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

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.

참고URL : https://stackoverflow.com/questions/9568150/what-is-a-c-delegate

반응형