Co to jest delegat C++?
Jaka jest ogólna idea delegata w C++? Czym są, w jaki sposób i do czego służą?
Chciałbym najpierw dowiedzieć się o nich w "czarnej skrzynce" sposób, ale trochę informacji na temat wnętrzności tych rzeczy byłoby również świetne.
To nie jest C++ w jego najczystszym lub najczystszym, ale zauważyłem, że baza kodu, w której pracuję, ma je w obfitości. Mam nadzieję, że zrozumiem je wystarczająco, abym mógł je po prostu wykorzystać i nie musiał zagłębiać się w straszne zagnieżdżony szablon awfulness.
Te dwa w artykułach Code Project wyjaśniają co mam na myśli, ale niezbyt zwięźle:
6 answers
Masz niesamowitą liczbę wyborów do osiągnięcia delegatów w C++. Oto te, które przyszły mi do głowy.
Opcja 1: funktory:
Obiekt funkcji może być utworzony przez implementację 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);
Opcja 2: wyrażenia lambda (tylko 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);
Opcja 3: Wskaźniki funkcji
int f(double d) { ... }
typedef int (*MyFuncT) (double d);
MyFuncT fp = &f;
int a = fp(3.14);
Opcja 4: Wskaźnik do funkcji Członkowskich (najszybszy rozwiązanie)
Zobacz Fast C++ Delegate (na projekt Code ).
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);
Opcja 5: std:: function
(lub boost::function
Jeśli biblioteka standardowa go nie obsługuje). Jest wolniejszy, ale najbardziej elastyczny.
#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)
Umożliwia ustawienie pewnych parametrów z góry, Wygodne wywołanie funkcji member dla przykład.
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
Opcja 7: szablony
Akceptuj wszystko, o ile pasuje do listy argumentów.
template <class FunctionT>
int DoSomething(FunctionT func)
{
return func(3.14);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-11 15:04:26
Delegat jest klasą, która zawija wskaźnik lub odniesienie do instancji obiektu, metodę składową klasy tego obiektu, która ma być wywołana na tej instancji obiektu i zapewnia metodę do wywołania tego wywołania.
Oto przykład:
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 );
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-04-05 07:04:31
Potrzeba implementacji delegatów C++ jest długotrwałym kłopotem dla społeczności C++. Każdy programista C++ chciałby je mieć, więc w końcu korzysta z nich pomimo faktu, że:
std::function()
wykorzystuje operacje sterty (i jest poza zasięgiem poważnego programowania wbudowanego).Wszystkie inne wdrożenia ustępują w kierunku przenośności lub standardowej zgodności w większym lub mniejszym stopniu (sprawdź, sprawdzając różne delegaty implementacje tutaj i na codeproject). Muszę jeszcze zobaczyć implementację, która nie używa wild reinterpret_casts, zagnieżdżoną klasę "prototypy", która miejmy nadzieję produkuje Wskaźniki funkcji o takim samym rozmiarze jak ten przekazany przez użytkownika, sztuczki kompilatora, takie jak first forward declare, następnie typedef, a następnie declare ponownie, Tym razem dziedzicząc z innej klasy lub podobnych shady technik. Chociaż jest to wielkie osiągnięcie dla implementatorów, którzy to zbudowali, to nadal jest smutnym świadectwem tego, jak C++ ewoluuje.
Rzadko zwraca się uwagę na to, że obecnie ponad 3 wersje standardu C++ nie zostały odpowiednio zaadresowane. (Lub brak funkcji językowych, które pozwalają na proste implementacje delegatów.)
Przy sposobie definiowania przez standard funkcji lambda w C++11 (każda lambda ma anonimowy, inny typ), sytuacja uległa poprawie tylko w niektórych przypadkach użycia. Ale dla przypadku użycia delegatów w API biblioteki (DLL), lambdas same nadal nie nadają się do użytku. Powszechną techniką jest najpierw spakowanie lambda do funkcji std::, a następnie przekazanie jej przez API.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-29 17:10:28
Bardzo prosto, delegat zapewnia funkcjonalność, jak powinien działać wskaźnik funkcji. Istnieje wiele ograniczeń wskaźników funkcji w C++. Delegat używa jakiegoś zakulisowego szablonu, aby utworzyć szablon-Klasa function-pointer-type-thing, który działa w sposób, w jaki chcesz.
Ie - możesz ustawić je tak, aby wskazywały na daną funkcję, możesz je przekazywać i wywoływać kiedykolwiek i gdziekolwiek chcesz.
Jest tu kilka bardzo dobrych przykładów:
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-10 12:11:35
Opcją dla delegatów w C++, która nie jest tu inaczej wymieniona, jest zrobienie tego w stylu C przy użyciu funkcji ptr i argumentu kontekstowego. Jest to prawdopodobnie ten sam wzór, który wielu zadających to pytanie stara się uniknąć. Ale wzorzec jest przenośny, wydajny i jest użyteczny w kodzie osadzonym i jądrze.
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);
...
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-03 18:20:34
Windows Runtime odpowiednik obiektu funkcji w standardowym C++. Można użyć całej funkcji jako parametru(w rzeczywistości jest to wskaźnik funkcji). Jest używany głównie w połączeniu z wydarzeniami. Delegat reprezentuje kontrakt, który podmioty obsługujące zdarzenia znacznie wypełniają. Ułatwia to pracę wskaźnika funkcji.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-25 16:03:12