85 Stimmen

wie boost::function und boost::bind funktionieren

Ich mag es nicht, wenn magische Kästchen in meinem Code verstreut sind... wie genau funktionieren diese beiden Klassen, die es ermöglichen, dass praktisch jede Funktion auf ein Funktionsobjekt abgebildet werden kann, selbst wenn die Funktion<> einen völlig anderen Parametersatz hat als der, den ich an boost::bind

Es funktioniert sogar mit unterschiedlichen Aufrufkonventionen (d.h. Membermethoden sind __thiscall unter VC, aber "normale" Funktionen sind im Allgemeinen __cdecl ou __stdcall für diejenigen, die mit C kompatibel sein müssen.

0 Stimmen

1 Stimmen

Nicht wirklich - in dieser Frage geht es um Bindung und Funktion

0 Stimmen

Ja, und damit bleibt immer noch die Frage, wie man map void MyClass:DoSomething(std::string str, int number) zu boost::function<void(int)> über bind(&MyClass::DoSomething, instance, "Hello World", _1) binden kann.

97voto

jpalecek Punkte 45829

boost::function erlaubt alles mit einem operator() mit der richtigen Signatur, die als Parameter gebunden werden soll, und das Ergebnis Ihrer Bindung kann mit einem Parameter aufgerufen werden int so kann es gebunden werden an function<void(int)> .

So funktioniert es (diese Beschreibung gilt gleichermaßen für std::function ):

boost::bind(&klass::member, instance, 0, _1) gibt ein Objekt wie dieses zurück

struct unspecified_type
{
  ... some members ...
  return_type operator()(int i) const { return instance->*&klass::member(0, i);
}

wo die return_type y int werden aus der Signatur von klass::member und der Funktionszeiger und der gebundene Parameter sind tatsächlich im Objekt gespeichert, aber das ist nicht wichtig

Jetzt, boost::function führt keine Typenprüfung durch: Es nimmt ein beliebiges Objekt und eine beliebige Signatur, die Sie in seinem Template-Parameter angeben, und erstellt ein Objekt, das gemäß Ihrer Signatur aufrufbar ist, und ruft das Objekt auf. Wenn das unmöglich ist, ist es ein Kompilierfehler.

boost::function ist eigentlich ein Objekt wie dieses:

template <class Sig>
class function
{
  function_impl<Sig>* f;
public:
  return_type operator()(argument_type arg0) const { return (*f)(arg0); }
};

wo die return_type y argument_type werden extrahiert aus Sig und f wird dynamisch auf dem Heap zugewiesen. Das ist notwendig, damit völlig unverbundene Objekte mit unterschiedlichen Größen sich an boost::function .

function_impl ist nur eine abstrakte Klasse

template <class Sig>
class function_impl
{
public:
  virtual return_type operator()(argument_type arg0) const=0;
};

Die Klasse, die die ganze Arbeit macht, ist eine konkrete Klasse, die von boost::function . Es gibt eine für jede Art von Objekt, das Sie zuordnen boost::function

template <class Sig, class Object>
class function_impl_concrete : public function_impl<Sig>
{
  Object o
public:
  virtual return_type operator()(argument_type arg0) const=0 { return o(arg0); }
};

Das heißt in Ihrem Fall, die Zuordnung zur Boost-Funktion:

  1. instanziiert einen Typ function_impl_concrete<void(int), unspecified_type> (das ist natürlich die Kompilierzeit)
  2. erzeugt ein neues Objekt dieses Typs auf dem Heap
  3. weist dieses Objekt dem f-Mitglied von boost::function zu

Wenn Sie das Funktionsobjekt aufrufen, ruft es die virtuelle Funktion seines Implementierungsobjekts auf, die den Aufruf an Ihre ursprüngliche Funktion weiterleitet.

DISCLAIMER: Beachten Sie, dass die Namen in dieser Erklärung absichtlich erfunden sind. Jede Ähnlichkeit mit realen Personen oder Charakteren ... Sie wissen es. Der Zweck war, die Prinzipien zu illustrieren.

0 Stimmen

So ist der Inhalt von struct unspecified_type (dh der Code in der Funktion operator()) grundsätzlich aus den Argumenten Vergangenheit zu boost::bind auf einer Fall-zu-Fall-Basis generiert, um jede Kombination und Anzahl von Argumenten zu ermöglichen?

1 Stimmen

Nein, es gibt Vorlagen für operator(), die alle Aritäten behandeln (und verschiedene Vorlagenargumente behandeln die Kombinationen)

0 Stimmen

Im letzten Codeblock heißt es: arg0) const=0 { return... ... Das habe ich noch nie gesehen. Ich habe ein nicht funktionierendes Beispiel in einem Forum gefunden, in dem eine Follow-up-Nachricht auf die C++-Faq verweist, in der erklärt wird, dass eine rein virtuelle Funktion einen Körper haben kann, aber ich kann keinen Code mit einer solchen Syntax kompilieren (Clang und Gcc).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X