wake-up-neo.com

Was ist die Verwendung von privaten statischen Memberfunktionen?

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?

32
rve

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:

  1. Sie gibt der Funktion Zugriff auf private und geschützte Member eines beliebigen Objekts der Klasse, wenn das Objekt statisch ist oder an die Funktion übergeben wird.
  2. Es ordnet die Funktion auf ähnliche Weise wie ein Namespace der Klasse zu.

In diesem Fall scheint nur der zweite Punkt zutreffend zu sein.

59
Mark Ransom

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 .

16
sbi

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();
}
...
4
dolphy

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.

2
Frerich Raabe

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).

0
Armen Tsirunyan