Ich habe also nur mit Funktionszeigern gearbeitet und mir ist aufgefallen, dass Sie das tun können:
%Vor%Der offensichtliche Vorteil ist, dass Verweise auf gültige Objekte verweisen (sofern sie nicht missbraucht werden) oder Funktionen in diesem Fall.
Die offensichtlichen Nachteile sind, dass Sie ein Array von Referenzen nicht speichern können und sie nicht für Mitgliedsfunktionszeiger verwenden können (zumindest soweit ich das beurteilen kann).
Meine Frage: benutzt jemand sie (dh Funktionsreferenzen , nicht Funktionszeiger), und wenn ja, in welchen Szenarien Sie fanden sie nützlich / hilfreich?
Der einzige Ort, an dem ich sehen kann, dass sie von Anfang an nützlich sind, ist das Binden eines Verweises auf eine bestimmte Funktion beim Arbeiten mit der bedingten Kompilierung.
Ich habe sie bereits zuvor verwendet, um Klassen anpassbar zu machen, indem Sie sie an den Konstruktor übergeben, ähnlich wie das Strategie-Muster
Ich denke, Ihre Beispielnutzung ist ziemlich gut. Wenn Sie einen gewöhnlichen Funktionszeiger verwenden und dann den Operanden address-of anwenden, erhalten Sie die Adresse des Funktionszeigers. Die Verwendung eines Verweises auf die Funktion führt zu der erwarteten Sache, da sie einen Zeiger auf die Funktion selbst zurückgibt.
Ich kann mir auch nicht viele Beispiele vorstellen. Die Einhaltung von Funktionsreferenzen hat, wie Sie bemerken, einige unschöne Konsequenzen. Eine andere möglicherweise unerwünschte Konsequenz ist, dass, wenn Sie als Klassenmitglied gehalten werden, Ihre Objekte nicht zuweisbar sind, wenn Sie keinen eigenen Operator schreiben = und nicht versuchen, die Funktionsreferenz neu zuzuweisen.
Ich denke, dass die meisten Verwendungen von Funktionsreferenzen implizit sind, ähnlich wie die meisten Verwendungen von Array-Verweisen - allerdings viel mehr, wenn Sie Argumente durch Verweis akzeptieren:
%Vor%Obwohl das Annehmen von Arrays durch Referenz den Vorteil hat, dass sie ihre Größeninformation nicht verlieren, scheint das Akzeptieren von Funktionen durch Referenz explizit keinen Vorteil zu haben (zumindest soweit ich sehen kann). Ich nehme an, dass die Existenz von Funktionsreferenzen weitgehend durch die idealistische Ansicht einer Referenz als ein Alias -Name eines Objekts oder einer Funktion gerechtfertigt ist, zusammen mit der Tatsache, dass sie Funktionen an solche Vorlagen weitergibt, die ihre akzeptieren Argument durch Verweis.
Ich würde wahrscheinlich vermeiden, sie zu benutzen, wenn ich sie nicht zwangsläufig brauchen würde. Konstante Funktionszeiger stellen auch nicht-neu zuweisbare Callables bereit und werden wahrscheinlich Verwirrungen vermeiden, wenn andere Programmierer, die möglicherweise mit diesen Sprachnischen nicht sehr vertraut sind, Ihren Code lesen. Es lohnt sich zu beachten, dass Vandervoorde & amp; Josuttis empfiehlt auch, sie zu vermeiden, um Verwirrung zu vermeiden (in ihrem Buch C ++ Templates - The Complete Guide).
Funktionsreferenzen machen es im Gegensatz zu Funktionszeigern schwieriger, sie aus einer ungültigen Quelle zu erstellen. Dies ist nützlich, wenn Sie einen Wrapper um eine C-Bibliothek erstellen - der C ++ - Code kann eine Callback-Funktion als Referenz verwenden und den Zeiger an die C-Bibliothek übergeben, wenn der übergebene Zeiger nicht NULL sein darf.
Es ist auch eine bequeme Möglichkeit, eine Funktion zu aliasieren, besonders in C ++ 11 mit dem neuen auto-Schlüsselwort:
%Vor%Ich habe sie in einem Plug-in-System verwendet, in dem Plug-in-DLLs zur Laufzeit geladen / entladen werden konnten. Ich würde in jeder DLL nach bekannten Symbolen suchen und sie in Funktionszeiger umwandeln.
zusätzlich zu der Verwendung als Strategie (wie von Robert Gould aufgezeigt), benutze ich sie häufig am Eingangspunkt zur (Template-) Metaprogrammierung. Eine Funktionsreferenz kann einfach von einem Template-Parameter übernommen werden; Von diesem Punkt an kann es durch mehrere Schichten von (Metaprogrammierungs) -Templates geleitet werden. Dies gilt natürlich auch für einen Funktionszeiger, aber der Verweis ist ein Alias und somit kommuniziert die Absicht deutlicher.
Um ein Beispiel zu geben: Wenn ein generisches Befehlsabfertigungssystem für eine Anwendung geschrieben wird, müssen viele verschiedene Operationen als Befehle angekündigt werden. Wir können eine einfache "Builder-Funktion" als Front-End für den Client-Code verwenden. Hinter den Kulissen nimmt diese Builder-Funktion die eigentliche Funktionssignatur als Template-Parameter auf, leitet (durch Template-Metaprogrammierung) die aktuellen Parameter- und Return-Type-Werte ab und wählt ggf. die geeignete Spezialisierung aus, um ein "Memento" und ein "Undo-Funktor" zu speichern. Diese Funktoren können dann entweder intern als Funktionszeiger oder unter Verwendung von Boost- oder Tr1- oder C ++ 11-Funktionsobjekten gespeichert werden. Auf diese Weise ist es möglich, ein typsicheres Befehlsaufruf- und "Rückgängig" -System zu erstellen.
Ich war an einem Projekt beteiligt, das ein Objektsystem in C mit Funktionszeigern und Strukturen implementieren wollte, um Klassen zu implementieren. Da die Funktionen ersetzt werden könnten, könnten sie eine Art Vererbungssystem implementieren. Glücklicherweise ist diese Anstrengung zusammengebrochen. Während die Aufgabe interessant war, war es keine gute Idee für das Projekt (wahrscheinlich keine gute Idee für irgendetwas in der Produktion).
Ich habe auch Funktionszeiger für ein DLL-basiertes Pluggable-Modulsystem verwendet, wie bereits erwähnt.
Tags und Links c++