Ich arbeite an einem C ++ - Projekt, in dem ich eine Reihe von mathematischen Funktionen habe, die ich ursprünglich als Teil einer Klasse geschrieben habe. Als ich mehr Code geschrieben habe, wurde mir klar, dass ich diese mathematischen Funktionen überall brauche.
Wo ist der beste Ort, um sie zu platzieren? Angenommen, ich habe Folgendes:
class A{
public:
int math_function1(int);
...
}
Und wenn ich eine andere Klasse schreibe, kann ich das math_function1
in dieser anderen Klasse nicht (oder zumindest weiß ich nicht, wie ich das machen soll) . Außerdem habe ich festgestellt, dass einige dieser Funktionen nicht wirklich mit Klasse A zusammenhängen. Sie schienen am Anfang zu stehen, aber jetzt kann ich sehen, dass es sich nur um mathematische Funktionen handelt.
Was ist in dieser Situation eine gute Praxis? Im Moment habe ich sie in die neuen Klassen kopiert, was sicher die schlechteste Praxis ist.
static
Keyword erfahren ?Antworten:
C ++ kann auch Funktionen enthalten, die keine Methoden sind. Wenn sie nicht zu einer Klasse gehören, platzieren Sie sie nicht in einer Klasse, sondern nur in einem globalen oder anderen Namespace-Bereich
quelle
math_function1(42)
ruft möglicherweise ein Mitglied der aktuellen Klasse auf;special_math_functions::math_function1(42)
ruft eindeutig eine unabhängige Funktion auf). Davon abgesehen::math_function(42)
liefert dies die gleiche Disambiguierung.// optional
. Nach Geschmack würzen.Hängt davon ab, wie das Projekt organisiert ist und welche Art von Entwurfsmustern Sie verwenden, vorausgesetzt, es handelt sich ausschließlich um Utility-Code. Sie haben die folgenden Optionen:
Beachten Sie, dass die erste Option die beste Option sein wird und die folgenden drei von begrenztem Nutzen sind. Das heißt, Sie könnten dann nur darauf stoßen, dass C # - oder Java-Programmierer etwas C ++ arbeiten oder dass Sie jemals an C # - oder Java-Code arbeiten, bei dem die Verwendung von Klassen obligatorisch ist.
quelle
Wie Sie bereits sagten, ist das Kopieren und Einfügen des Codes die schlechteste Form der Wiederverwendung von Code. Wenn Sie Funktionen haben, die keiner Ihrer Klassen angehören oder in mehreren Szenarien verwendet werden können, ist eine Helfer- oder Utility-Klasse der beste Ort, um sie zu platzieren. Wenn sie keine Instanzdaten verwenden, können sie statisch gemacht werden, sodass Sie keine Instanz der Utility-Klasse erstellen müssen, um sie zu verwenden.
Sehen Sie hier für eine Diskussion der statischen Member - Funktionen in native C ++ und hier für statische Klassen in Managed C ++. Sie können diese Dienstprogrammklasse dann überall dort verwenden, wo Sie Ihren Code eingefügt hätten.
In .NET werden Dinge wie
Min()
undMax()
als statische Member für dieSystem.Math
Klasse bereitgestellt .Wenn alle Funktionen Mathe bezogen sind und Sie würden otherwiese eine gigantische haben
Math
Klasse, könnten Sie es wollen weiter brechen und haben Klassen wieTrigonometryUtilities
,EucledianGeometryUtilities
und so weiter.Eine andere Option wäre, geteilte Funktionalität in eine Basisklasse der Klassen zu setzen, die diese Funktionalität benötigen. Dies funktioniert gut, wenn die Funktionen in Fragen Instanzdaten verarbeiten müssen. Dieser Ansatz ist jedoch auch weniger flexibel, wenn Sie die Mehrfachvererbung vermeiden und sich nur an eine Basisklasse halten möchten, da Sie Ihre eine Basis "verbrauchen" würden Klasse, nur um Zugriff auf einige gemeinsame Funktionen zu erhalten.
quelle
Disambiguieren Sie den Begriff "Hilfsfunktion". Eine Definition ist eine Komfortfunktion, die Sie ständig verwenden, um bestimmte Aufgaben zu erledigen. Diese können im Hauptnamensraum leben und ihre eigenen Header usw. haben. Die andere Helferfunktionsdefinition ist eine Dienstprogrammfunktion für eine einzelne Klasse oder Klassenfamilie.
Now
isPrinter
ist für jeden Code einschließlich seines Headers verfügbar,print_alignment_page
erfordert jedoch eineusing namespace printer_utils::Xerox;
Direktive. Man kann es auch als bezeichnenklarer zu sein.
Die C ++ STL verfügt über den
std::
Namespace, der fast alle Klassen und Funktionen abdeckt, teilt sie jedoch kategorisch in über 17 verschiedene Header auf, damit der Codierer die Klassennamen, Funktionsnamen usw. aus dem Weg räumen kann, wenn er schreiben möchte ihre eigenen.Tatsächlich wird NICHT empfohlen, sie
using namespace std;
in einer Header-Datei oder, wie so oft, als erste Zeile im Inneren zu verwendenmain()
.std::
besteht aus 5 Buchstaben und scheint oft eine lästige Pflicht zu sein, die Funktion, die man verwenden möchte (besondersstd::cout
undstd::endl
!), vorzustellen, aber sie erfüllt einen Zweck.Das neue C ++ 11 enthält einige Subnamespaces für spezielle Dienste wie
das kann zur Verwendung gebracht werden.
Eine nützliche Technik ist die Namespace-Komposition . Einer definiert einen benutzerdefinierten Namespace, der die Namespaces enthält, die Sie für Ihre bestimmte
.cpp
Datei benötigen, und verwendet diese anstelle einer Reihe vonusing
Anweisungen für jedes Element in einem Namespace, das Sie möglicherweise benötigen.Diese Technik begrenzt die Exposition gegenüber dem Ganzen
std:: namespace
( sie ist groß! ) Und ermöglicht es, saubereren Code für die häufigsten Codezeilen zu schreiben, die am häufigsten geschrieben werden.quelle
Möglicherweise möchten Sie es in eine Vorlagenfunktion einfügen, um es für verschiedene Arten von Ganzzahlen und / oder Gleitkommazahlen verfügbar zu machen:
Sie können auch nette benutzerdefinierte Typen erstellen, die beispielsweise große oder komplexe Zahlen darstellen, indem Sie relevante Operatoren für Ihren benutzerdefinierten Typ überladen, um sie vorlagenfreundlich zu gestalten.
quelle