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.
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:
function_impl_concrete<void(int), unspecified_type>
(das ist natürlich die Kompilierzeit)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.