Ich habe mir den request parser aus dem Beispiel boost :: asio angesehen und habe mich gefragt, warum die privaten Member-Funktionen wie is_char()
static
sind. :
class request_parser
{
...
private:
static bool is_char(int c);
...
};
Es wird in der Funktion consume verwendet, die keine statische Funktion ist:
boost::tribool request_parser::consume(request& req, char input)
{
switch (state_)
{
case method_start:
if (!is_char(input) || is_ctl(input) || is_tspecial(input))
{
return false;
}
...
Nur Memberfunktionen können is_char()
aufrufen, und keine statische Memberfunktion ruft is_char()
auf. Gibt es einen Grund, warum diese Funktionen statisch sind?
Diese Funktion könnte leicht freistehend gemacht worden sein, da kein Objekt der Klasse erforderlich ist, um darin zu arbeiten. Wenn Sie eine Funktion zu einem statischen Member einer Klasse machen, anstatt zu einer freien Funktion, haben Sie zwei Vorteile:
In diesem Fall scheint nur der zweite Punkt zutreffend zu sein.
Gibt es einen Grund, warum diese Funktionen statisch sind?
Nicht-static
Mitgliedsfunktionen haben einen versteckten zusätzlichen Parameter namens this
. Die Weitergabe ist nicht kostenlos, daher kann das Erstellen einer private
-Funktion static
als Mittel zur -Optimierung angesehen werden .
Es kann aber auch als Mittel gesehen werden, um Ihre Anforderungen/Ihr Design in Ihrem Code auszudrücken : Wenn diese Funktion nicht benötigt wird Um auf Elementdaten der Klasse zu verweisen, warum sollte es eine Nicht-static
-Elementfunktion sein?
Wenn Sie jedoch den Typ einer Mitgliedsfunktion public
oder private
, static
ändern, müssen alle Clients neu kompiliert werden. Wenn dies für eine private
-Funktion erforderlich ist, die diese Clients niemals verwenden können, ist dies eine Verschwendung von Ressourcen. Daher verschiebe ich normalerweise so viele Funktionen wie möglich aus den privaten Teilen der Klasse in einen nicht benannten Namespace in der Implementierungsdatei .
Bei diesem speziellen Beispiel handelt es sich bei der Wahl einer static is_char()
wahrscheinlich um eine Dokumentation. Die Absicht ist es, Ihnen zu vermitteln, dass die is_char()
-Methode nicht von einer bestimmten Instanz der Klasse abhängt, sondern die Funktionalität ist spezifisch für die Klasse selbst .
Mit anderen Worten, indem sie static
gemacht werden, sagen sie, dass is_char()
eine nützliche Funktion ist ... eine Funktion, die unabhängig vom Zustand einer gegebenen Instanz verwendet werden kann. Indem sie es private
machen, sagen sie, dass Sie (als Kunde) nicht versuchen sollten, es zu verwenden. Entweder macht es nicht das, was Sie glauben, oder es wird auf sehr beschränkte, kontrollierte Weise implementiert.
Die Antwort von @ Mark Ransom ist ein guter Punkt für die praktische Verwendung einer privaten statischen Memberfunktion. Insbesondere hat diese Memberfunktion Zugriff auf private und geschützte Member eines statischen Objekts oder einer übergebenen Instanz eines instanziierten Objekts.
Eine häufige Anwendung hiervon ist es, eine pthread-Implementierung auf eine objektorientierte Weise zu abstrahieren. Ihre Thread-Funktion muss statisch sein. Wenn Sie sie jedoch als private deklarieren, beschränkt sich der Zugriff auf diese Funktion auf die Klasse (auf alle außer den am meisten bestimmten). Dem Thread kann eine Instanz der Klasse übergeben werden, in der er "versteckt" ist, und hat jetzt Zugriff auf die Logik unter Verwendung der Member-Daten des Objekts.
Vereinfachtes Beispiel:
[MyWorkerClass.h]
...
public:
bool createThread();
private:
int getThisObjectsData();
pthread_t myThreadId_;
static void* myThread( void *arg );
...
[MyWorkerClass.cpp]
...
bool MyWorkerClass::createThread()
{
...
int result = pthread_create(myThreadId_,
NULL,
myThread),
this);
...
}
/*static*/ void* MyWorkerClass::myThread( void *arg )
{
MyWorkerClass* thisObj = (MyWorkerClass*)(arg);
int someData = thisObj->getThisObjectsData();
}
...
Es ist statisch, da es keinen Zugriff auf Mitgliedervariablen von request_parser
-Objekten erfordert. Wenn Sie es statisch machen, wird die Funktion dadurch entkoppelt, da dadurch die Statusmenge reduziert wird, auf die die Funktion zugreifen kann.
Es wäre sogar noch besser gewesen, wenn diese Funktion überhaupt nicht Teil der Klasse request_parser
wäre. Stattdessen hätte sie (möglicherweise in einem Namensraum) eine freie Funktion in der Datei .cpp
sein sollen.
Der Punkt ist nichtwoverwendet wird. Die Frage istwasverwendet. Wenn seine Definition keine nicht-statischen Member verwendet, würde ich die Funktion statisch machen, nach dem gleichen Prinzip, dass ich keinen redundanten Parameter an eine Funktion übergeben würde (es sei denn, sie würden in Überladungserhebungen verwendet).