Wie erstellt man eine statische Klasse in C ++? Ich sollte in der Lage sein, etwas zu tun wie:
cout << "bit 5 is " << BitParser::getBitAt(buffer, 5) << endl;
Angenommen, ich habe die BitParser
Klasse erstellt. Wie würde die BitParser
Klassendefinition aussehen?
Antworten:
Wenn Sie nach einer Möglichkeit suchen, das Schlüsselwort "static" auf eine Klasse anzuwenden, wie dies beispielsweise in C # möglich ist, können Sie dies nicht ohne die Verwendung von Managed C ++ tun.
Für das Aussehen Ihres Beispiels müssen Sie lediglich eine öffentliche statische Methode für Ihr BitParser-Objekt erstellen. Wie so:
BitParser.h
BitParser.cpp
Mit diesem Code können Sie die Methode auf dieselbe Weise wie Ihren Beispielcode aufrufen.
Ich hoffe, das hilft! Prost.
quelle
private: BitParser() {}
Dadurch wird verhindert, dass jemand Instanzen erstellt.BitParser() = delete;
ist, die Absicht, den Konstruktor zu entfernen, richtig zu vermitteln (und ihn nicht nur als zu verbergenprivate
).Betrachten Sie die Lösung von Matt Price .
Was Sie wollen, ist, ausgedrückt in C ++ - Semantik, Ihre Funktion (denn es ist eine Funktion) in einen Namespace zu setzen.
Bearbeiten 2011-11-11
In C ++ gibt es keine "statische Klasse". Das nächste Konzept wäre eine Klasse mit nur statischen Methoden. Beispielsweise:
Sie müssen sich jedoch daran erinnern, dass "statische Klassen" Hacks in Java-ähnlichen Sprachen (z. B. C #) sind, die keine Nichtmitgliedsfunktionen haben können. Sie müssen sie stattdessen als statische Methoden in Klassen verschieben.
In C ++ möchten Sie wirklich eine Nichtmitgliedsfunktion, die Sie in einem Namespace deklarieren:
Warum ist das so?
In C ++ ist der Namespace für das Muster "Statische Java-Methode" leistungsfähiger als Klassen, weil:
Schlussfolgerung: Kopieren Sie das Java / C # -Muster nicht in C ++. In Java / C # ist das Muster obligatorisch. Aber in C ++ ist es ein schlechter Stil.
Bearbeiten 2010-06-10
Es gab ein Argument für die statische Methode, da manchmal eine statische private Mitgliedsvariable verwendet werden muss.
Ich bin etwas anderer Meinung, wie unten gezeigt:
Die "Static Private Member" -Lösung
Erstens heißt myGlobal myGlobal, da es immer noch eine globale private Variable ist. Ein Blick auf die CPP-Quelle verdeutlicht Folgendes:
Auf den ersten Blick scheint die Tatsache, dass die freie Funktion barC nicht auf Foo :: myGlobal zugreifen kann, aus Sicht der Kapselung eine gute Sache zu sein ... Es ist cool, weil jemand, der sich das HPP ansieht, nicht darauf zugreifen kann (es sei denn, er greift auf Sabotage zurück) Foo :: myGlobal.
Wenn Sie es sich jedoch genau ansehen, werden Sie feststellen, dass es sich um einen kolossalen Fehler handelt: Nicht nur Ihre private Variable muss im HPP deklariert sein (und somit für die ganze Welt sichtbar sein, obwohl sie privat ist), sondern Sie müssen sie auch deklarieren im selben HPP alle (wie in ALLEN) Funktionen, die berechtigt sind, darauf zuzugreifen !!!
Wenn Sie also ein privates statisches Mitglied verwenden, gehen Sie nackt mit der Liste Ihrer Liebenden, die auf Ihre Haut tätowiert sind, nach draußen: Niemand darf berühren, aber jeder kann einen Blick darauf werfen. Und der Bonus: Jeder kann die Namen derjenigen haben, die berechtigt sind, mit Ihren Geheimnissen zu spielen.
private
in der Tat ... :-DDie Lösung "Anonyme Namespaces"
Anonyme Namespaces haben den Vorteil, dass sie Dinge wirklich privat machen.
Zunächst der HPP-Header
Nur um sicherzugehen, dass Sie bemerkt haben: Es gibt keine nutzlose Erklärung von barB oder myGlobal. Das bedeutet, dass niemand, der den Header liest, weiß, was sich hinter barA verbirgt.
Dann ist der CPP:
Wie Sie sehen, können fooA und fooB wie die sogenannte "static class" -Deklaration weiterhin auf myGlobal zugreifen. Aber sonst kann niemand. Und niemand außerhalb dieses CPP weiß, dass fooB und myGlobal überhaupt existieren!
Im Gegensatz zu der "statischen Klasse", die nackt mit ihrem auf die Haut tätowierten Adressbuch läuft , ist der "anonyme" Namespace vollständig bekleidet , was AFAIK besser zu verkapseln scheint.
Ist es wirklich wichtig?
Es sei denn, die Benutzer Ihres Codes sind Saboteure (ich lasse Sie als Übung herausfinden, wie man mit einem schmutzigen, nicht definierten Hack auf den privaten Teil einer öffentlichen Klasse zugreifen kann ...), was
private
istprivate
, auch wenn es so ist ist imprivate
Abschnitt einer Klasse sichtbar, die in einem Header deklariert ist.Wenn Sie jedoch eine weitere "private Funktion" mit Zugriff auf das private Mitglied hinzufügen müssen, müssen Sie sie dennoch der ganzen Welt deklarieren, indem Sie den Header ändern. Dies ist für mich ein Paradoxon: Wenn ich die Implementierung von ändere Mein Code (der CPP-Teil), dann sollte sich die Schnittstelle (der HPP-Teil) NICHT ändern. Zitat von Leonidas: " Das ist ENCAPSULATION! "
Bearbeiten 20.09.2014
Wann sind statische Klassenmethoden tatsächlich besser als Namespaces mit Nicht-Member-Funktionen?
Wenn Sie Funktionen gruppieren und diese Gruppe einer Vorlage zuordnen müssen:
Denn wenn eine Klasse ein Vorlagenparameter sein kann, können Namespaces dies nicht.
quelle
#define private public
in die Header einzufügen ... ^ _ ^ ...utilities
Namespace verwendet. Auf diese Weise kann diese Funktion einem Unit-Testnamespace
Willen springt, erhält er keinen Zugang zu Ihrenglobal
, wenn auch versteckten Mitgliedern? Natürlich müssten sie raten, aber wenn Sie Ihren Code nicht absichtlich verschleiern, sind Variablennamen ziemlich einfach zu erraten.Sie können auch eine kostenlose Funktion in einem Namespace erstellen:
In BitParser.h
In BitParser.cpp
Im Allgemeinen wäre dies die bevorzugte Methode zum Schreiben des Codes. Wenn kein Objekt benötigt wird, verwenden Sie keine Klasse.
quelle
statische Klassen sind nur der Compiler, der Sie in der Hand hält und Sie daran hindert, Instanzmethoden / -variablen zu schreiben.
Wenn Sie nur eine normale Klasse ohne Instanzmethoden / -variablen schreiben, ist dies dasselbe, und dies würden Sie in C ++ tun
quelle
static
200 Mal zu schreiben oder auszuschneiden / einzufügen, wäre eine gute Sache.In C ++ möchten Sie eine statische Funktion einer Klasse erstellen (keine statische Klasse).
Sie sollten dann in der Lage sein, die Funktion mit BitParser :: getBitAt () aufzurufen, ohne ein Objekt zu instanziieren, von dem ich annehme, dass es das gewünschte Ergebnis ist.
quelle
Kann ich so etwas schreiben
static class
?Nein , gemäß C ++ 11 N3337 Standardentwurf Anhang C 7.1.1:
Und wie
struct
,class
ist auch eine Art Erklärung.Dasselbe kann durch Durchlaufen des Syntaxbaums in Anhang A abgeleitet werden.
Es ist interessant festzustellen, dass dies
static struct
in C legal war, aber keine Auswirkungen hatte: Warum und wann sollten statische Strukturen in der C-Programmierung verwendet werden?quelle
Wie hier angemerkt, könnte ein besserer Weg, dies in C ++ zu erreichen, die Verwendung von Namespaces sein. Da hier jedoch niemand das
final
Schlüsselwort erwähnt hat, poste ich, wie ein direktes Äquivalentstatic class
von C # in C ++ 11 oder höher aussehen würde:quelle
Sie können eine statische Klasse in C ++ haben, wie bereits erwähnt. Eine statische Klasse ist eine Klasse, für die keine Objekte instanziiert wurden. In C ++ kann dies erreicht werden, indem der Konstruktor / Destruktor als privat deklariert wird. Das Endergebnis ist das gleiche.
quelle
In Managed C ++ lautet die statische Klassensyntax: -
... besser spät als nie...
quelle
Dies ähnelt der Vorgehensweise von C # in C ++
In C # file.cs können Sie private var in einer öffentlichen Funktion haben. In einer anderen Datei können Sie sie verwenden, indem Sie den Namespace mit der folgenden Funktion aufrufen:
So können Sie dasselbe in C ++ tun:
SharedModule.h
SharedModule.cpp
OtherFile.h
OtherFile.cpp
quelle
Im Gegensatz zu anderen verwalteten Programmiersprachen hat "statische Klasse" in C ++ KEINE Bedeutung. Sie können die statische Elementfunktion verwenden.
quelle
Ein Fall, in dem Namespaces möglicherweise nicht so nützlich sind, um "statische Klassen" zu erreichen, ist die Verwendung dieser Klassen, um eine Komposition über Vererbung zu erreichen. Namespaces können keine Freunde von Klassen sein und können daher nicht auf private Mitglieder einer Klasse zugreifen.
quelle
Eine (der vielen) Alternativen, aber die (meiner Meinung nach) eleganteste (im Vergleich zur Verwendung von Namespaces und privaten Konstruktoren zur Emulation des statischen Verhaltens), um das Verhalten "Klasse, die nicht instanziiert werden kann" in C ++ zu erreichen, wäre: Deklarieren Sie eine reine virtuelle Dummy-Funktion mit dem
private
Zugriffsmodifikator.Wenn Sie C ++ 11 verwenden, können Sie zusätzliche Anstrengungen unternehmen, um sicherzustellen, dass die Klasse nicht vererbt wird (um das Verhalten einer statischen Klasse nur zu emulieren), indem Sie den
final
Bezeichner in der Klassendeklaration verwenden, um die anderen Klassen daran zu hindern, sie zu erben .So albern und unlogisch es auch klingen mag, C ++ 11 ermöglicht die Deklaration einer "reinen virtuellen Funktion, die nicht überschrieben werden kann", die Sie neben der Deklaration der Klasse verwenden können
final
, um das statische Verhalten rein und vollständig zu implementieren, da dies zu dem Ergebnis führt Klasse darf nicht vererbbar sein und die Dummy-Funktion darf in keiner Weise überschrieben werden.quelle