webentwicklung-frage-antwort-db.com.de

wie boost :: function und boost :: bind funktionieren

Ich mag es nicht, wenn magische Kästchen über meinen Code verstreut sind ... Wie genau funktionieren diese beiden Klassen, damit im Grunde genommen jede Funktion einem Funktionsobjekt zugeordnet werden kann, selbst wenn die Funktion <> einen völlig anderen Parametersatz hat als der, an den sie übergeben wird boost::bind

Es funktioniert sogar mit verschiedenen Aufrufkonventionen (d. H. Member-Methoden sind __thiscall unter VC, aber "normale" Funktionen sind in der Regel __cdecl oder __stdcall für diejenigen, die mit C kompatibel sein müssen.

81
Fire Lancer

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

So funktioniert es (diese Beschreibung gilt auch 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);
}

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

Jetzt führt boost::function Keine Typprüfung durch: Es werden alle Objekte und Signaturen verwendet, die Sie in den Vorlagenparametern angeben, und es wird ein Objekt erstellt, das entsprechend Ihrer Signatur aufrufbar ist, und das Objekt wird aufgerufen. Wenn das unmöglich ist, ist es ein Kompilierungsfehler.

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

dabei werden return_type und argument_type aus Sig extrahiert und f wird dynamisch auf dem Heap zugewiesen. Dies ist erforderlich, damit völlig unabhängige Objekte mit unterschiedlichen Größen an boost::function Gebunden werden können.

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 erledigt, ist eine konkrete Klasse, die von boost::function Abgeleitet ist. Für jeden Objekttyp, den Sie boost::function Zuweisen, gibt es einen.

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 bedeutet 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. erstellt ein neues Objekt dieses Typs auf dem Heap
  3. weist dieses Objekt dem Element f von boost :: function zu

Wenn Sie das Funktionsobjekt aufrufen, ruft es die virtuelle Funktion seines Implementierungsobjekts auf, wodurch der Aufruf an Ihre ursprüngliche Funktion weitergeleitet wird.

HAFTUNGSAUSSCHLUSS: 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 es, die Prinzipien zu veranschaulichen.

94
jpalecek