Statisch, Nichtmitglied oder statische Nichtmitgliedfunktion?

8

Jedes Mal wenn ich eine Funktionalität habe, die in Richtung "Dienstprogramm" geht, frage ich mich, welche Option die beste ist. Zum Beispiel, Drucken von Nachrichtenstrukturen (eigene oder externe), einige Kodierung / Dekodierung Code oder einfach ein paar nützliche Konvertierungsfunktionen in dem Kontext, den ich arbeite.

Die Optionen, über die ich nachdenke, sind:

1) Statische Funktion in der Hilfsklasse / struct.

%Vor%

2) Nicht-Mitglieder-Funktion.

%Vor%

3) Statische Nichtmitgliedsfunktion.

%Vor%

In einigen Fällen kann es notwendig sein, im "Dienstprogramm" einen Zustand zu initialisieren oder beizubehalten, also wähle ich Option 1, um den "globalen" Zustand zu vermeiden. Wenn es jedoch keinen Zustand gibt, der eingehalten werden muss, sollte ich dann Option 2 oder 3? Was ist der praktische Unterschied zwischen Option 2 und 3?

Was ist wichtig zu beachten und gibt es einen bevorzugten Weg , um dies zu erreichen? Danke!

    
murrekatt 05.08.2011, 08:06
quelle

3 Antworten

12

Der Unterschied zwischen den Optionen 2 und 3 besteht darin, dass im zweiten Fall die Funktion innerhalb der Übersetzungseinheit liegt. Wenn die Funktion nur in der cpp definiert ist, sollte dies die Option sein (was in etwa einem unbenannten Namespace entspricht - was eine vierte zu berücksichtigende Option ist, wiederum ungefähr gleich 3).

Wenn die Funktion von verschiedenen Übersetzungseinheiten verwendet werden soll, sollten Sie mit der Option 2 fortfahren. Die Funktion wird einmal kompiliert (außer Sie markieren sie als inline und geben die Definition in der Kopfzeile an), während Sie Option 3 wählen Der Compiler erstellt in jeder Übersetzungseinheit eine interne Kopie.

Ab Option 1 würde ich es vermeiden. In Java oder C # sind Sie gezwungen, überall Klassen zu verwenden, und Sie erhalten schließlich Dienstprogrammklassen , wenn Operationen dem Objektparadigma nicht gut zugeordnet werden. In C ++ dagegen können Sie diese Operationen als freistehende Funktionen bereitstellen, und Sie müssen die zusätzliche Ebene nicht hinzufügen. Wenn Sie sich für die -Werkzeugklasse entscheiden, vergessen Sie nicht, die Erstellung der Objekte zu deaktivieren.

Ob sich die Funktionen auf Klassen- oder Namespace-Ebene befinden, wirkt sich auf die Suche aus und wirkt sich auf den Benutzercode aus. Statische Memberfunktionen müssen immer mit dem Klassennamen qualifiziert werden, es sei denn, Sie befinden sich innerhalb des Klassenbereichs, während es verschiedene Möglichkeiten gibt, Namespace-Funktionen in den Geltungsbereich zu bringen. Als anschauliches Beispiel betrachten Sie eine Reihe von mathematischen Hilfsfunktionen und den Aufruf von Code:

%Vor%

Was Sie leichter zu lesen finden, ist eine andere Geschichte, aber ich bevorzuge die erstere: Innerhalb der Funktion kann ich den Namensraum auswählen und mich dann nur auf die Operationen konzentrieren und Nachschlageprobleme ignorieren.

    
David Rodríguez - dribeas 05.08.2011, 08:19
quelle
8

Verwenden Sie keine Klassen als Namespaces. Eine freie Funktion (dh eine Nicht-Member-Funktion) innerhalb eines Namensraums ist die einfachste Sache .

Außerdem sollte die Funktion nicht statisch sein, wenn sie über mehrere Übersetzungseinheiten hinweg verwendet werden soll. Andernfalls wird es dupliziert.

Die Verwendung von Klassen als Namespace ist dumm: Warum sollte man eine Klasse machen, die man nicht instanziiert?

Wenn ein Zustand beibehalten werden soll, dann haben Sie irgendwo einen globalen Zustand: statische Variable innerhalb der Funktion, Dienstprogramm globales Objekt (möglicherweise in einem "privaten" Namensraum oder als statische globale Variable in einer Ihrer Übersetzungseinheiten). Schreiben Sie keine Klassen, die Sie nicht instanziieren.

Leider werden Leute mit einem C # / Java-Hintergrund verwendet, um dieses dumme Ding zu machen, aber es ist, weil ihre Sprachdesigner einseitig entschieden haben, dass freie Funktionen böse sind. Ob sie erschossen werden sollen oder nicht, ist eine Frage der Religion.

Als letztes Wort der Warnung: Der globale Zustand sollte selten verwendet werden. Tatsächlich verbindet es Ihren Code mit der Existenz des globalen Zustands auf eine Weise, die Sie nicht kontrollieren, wenn der Code wächst. Sie sollten sich immer fragen, warum Sie diese Kopplung nicht explizit machen.

    
Alexandre C. 05.08.2011 08:08
quelle
-1

Ich benutze struct mit statischen Funktionen, weil es eine etwas bessere Isolation bietet als Nicht-Member-Funktionen in Namespaces (wegen der Vermeidung von Koenig-Lookup).

Um ein Beispiel zu geben, was ich vermeiden möchte:

%Vor%     
quant_dev 05.08.2011 08:17
quelle