web-dev-qa-db-fra.com

Quelle est l'utilisation de fonctions membres statiques privées?

Je regardais le requête parser de l'exemple boost :: asio et je me demandais pourquoi les fonctions privées telles que is_char() sont static? :

class request_parser
{
  ...
  private:
    static bool is_char(int c);
  ...
};

Il est utilisé dans la fonction consume qui n’est pas une fonction statique:

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;
    }
    ...

Seules les fonctions membres peuvent appeler is_char() et aucune fonction membre statique n'appelle is_char(). Y a-t-il une raison pour laquelle ces fonctions sont statiques?

32
rve

Cette fonction aurait facilement pu être rendue autonome, puisqu’elle n’exige pas qu’un objet de la classe soit utilisé à l’intérieur. Faire d'une fonction un membre statique d'une classe plutôt qu'une fonction libre présente deux avantages:

  1. Il donne à la fonction l'accès aux membres privés et protégés de tout objet de la classe, si l'objet est statique ou s'il est transmis à la fonction;
  2. Il associe la fonction à la classe de la même manière qu'un espace de noms.

Dans ce cas, il semble que seul le deuxième point s'applique.

59
Mark Ransom

Y a-t-il une raison pour laquelle ces fonctions sont statiques?

Les fonctions membres non -static ont un paramètre supplémentaire masqué appelé this. Passer ceci n'est pas gratuit, donc créer une private fonction static peut être vu comme un moyen deoptimisation.
Mais cela peut aussi être vu comme un moyen deexprimer vos exigences/conception dans votre code: Si cette fonction n'a pas besoin de faire référence à des données membres de la classe, pourquoi être une fonction membre non -static

Toutefois, si vous modifiez le type d'une fonction membre, public ou private, static ou non, vous devrez recompiler tous les clients. Si cela doit être fait pour une fonction private que ces clients ne peuvent jamais utiliser, c'est un gaspillage de ressources. Par conséquent, je déplace généralement autant de fonctions que possible des parties privées de la classe vers un espace de nomsunnamed dans le fichier d'implémentation

14
sbi

Pour cet exemple spécifique, le choix d'une static is_char() est très probablement un choix de documentation. L'intention est de vous faire comprendre que la méthode is_char() n'est pas contenue dans une instance spécifique de la classe, mais que la fonctionnalité est spécifique à la classe elle-même

En d'autres termes, en le rendant static, ils disent que is_char() est une fonction d'utilité ... qui peut être utilisée indépendamment de l'état d'une instance donnée. En le rendant private, ils disent que vous (en tant que client) ne devez pas essayer de l’utiliser. Il ne fait pas ce que vous pensez, ou est mis en œuvre de manière très contrainte et contrôlée.

La réponse de @Mark Ransom soulève un bon point pour l'utilisation pratique d'une fonction membre statique privée. Plus précisément, cette fonction de membre a accès aux membres privés et protégés d'un objet statique ou d'une instance passée d'un objet instancié.

Une application courante consiste à résumer une implémentation pthread de manière plus ou moins orientée objet. Votre fonction de thread doit être statique, mais la déclarer privée limite l'accessibilité de cette fonction à la classe (à l'exception des plus déterminées). Le thread peut recevoir une instance de la classe dans laquelle il est "masqué" et a maintenant accès à la logique pour utiliser la logique en utilisant les données de membre de l'objet.

Exemple simpliste:

[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

C'est statique, car il ne nécessite aucun accès aux variables membres des objets request_parser. Par conséquent, le rendre statique dissocie la fonction, car cela réduit la quantité d'états auxquels la fonction peut accéder.

Pour ce que cela vaut, cela aurait été encore mieux si cette fonction ne faisait pas du tout partie de la classe request_parser; à la place, elle aurait dû être (éventuellement dans un espace de noms) une fonction libre dans le fichier .cpp.

2
Frerich Raabe

Le point n'est pasil est utilisé. La question estce queil utilise. Si sa définition n'utilise aucun membre non statique, je rendrais la fonction statique, selon le même principe, à savoir que je ne transmettrais pas de paramètre redondant à une fonction quelconque (à moins que ces paramètres ne soient utilisés dans la résolution de surcharge).

0
Armen Tsirunyan