¿Cuál es el uso de las funciones de miembros estáticos privados?


Estaba mirando el analizador de solicitudes del ejemplo boost::asio y me preguntaba por qué las funciones de los miembros privados como is_char() son static? :

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

Se utiliza en la función consumir que no es una función estática:

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

Solo las funciones miembro pueden llamar a is_char() y ninguna función miembro estática está llamando a is_char(). Entonces, ¿hay alguna razón por la que estas funciones son estáticas?

Author: rve, 2011-06-23

5 answers

Esta función podría haberse hecho fácilmente independiente, ya que no requiere un objeto de la clase para operar dentro. Hacer de una función un miembro estático de una clase en lugar de una función libre da dos ventajas:

  1. Da a la función acceso a miembros privados y protegidos de cualquier objeto de la clase, si el objeto es estático o se pasa a la función;
  2. Asocia la función con la clase de una manera similar a un espacio de nombres.

En este caso aparece sólo el segundo punto se aplica.

 56
Author: Mark Ransom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-22 20:18:27

Entonces, ¿hay alguna razón por la que estas funciones son estáticas?

Las funciones miembro no-static tienen un parámetro adicional oculto llamado this. Pasar esto no viene gratis, por lo que hacer una función private static puede verse como un medio de optimización.
Pero también puede ser visto como un medio de expresar sus requisitos / diseño en su código: Si esa función no necesita hacer referencia a ningún dato miembro de la clase, ¿por qué debería ¿es una función no miembrostatic?

Sin embargo, cambiando el tipo de cualquier función miembro, public o private, static o no, requerirá que todos los clientes recompilen. Si esto necesita hacerse para una función private que esos clientes nunca pueden usar, eso es un desperdicio de recursos. Por lo tanto, generalmente muevo tantas funciones como sea posible de las partes privadas de la clase a un espacio de nombres sin nombre en el archivo de implementación.

 13
Author: sbi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-17 15:30:12

Para este ejemplo específico, la elección de un static is_char() es probablemente una de documentación. La intención es impresionarle que el método is_char() no está contraindicado en una instancia específica de la clase, pero la funcionalidad es específica de la propia clase.

En otras palabras, al hacerlo static están diciendo que is_char() es una especie de función de utilidad...uno que puede ser utilizado independientemente del estado de una instancia dada. Al hacerlo private, están diciendo que usted (como un cliente) no debe tratar de usarlo. O bien no hace lo que crees que hace, o se implementa de una manera muy restringida y controlada.

La respuesta de@Mark Ransom trae un buen punto para el uso práctico de una función de miembro estático privado. Específicamente, esa función miembro tiene acceso a miembros privados y protegidos de un objeto estático o una instancia pasada de un objeto instanciado.

Una aplicación común de esto es abstraer una implementación de pthread en algo de una manera orientada a objetos. Su función thread debe ser estática, pero declararla privada limita la accesibilidad de esa función a la clase (a todos menos a los más determinados). Al hilo se le puede pasar una instancia de la clase en la que está "oculto", y ahora tiene acceso para realizar la lógica utilizando los datos de miembro del objeto.

Ejemplo simplista:

[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
Author: dolphy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-23 13:48:36

Es estático, ya que no requiere acceso a ninguna variable miembro de los objetos request_parser. Por lo tanto, haciéndolo estático desacopla la función ya que reduce la cantidad de estado al que la función puede acceder.

Por si sirve de algo, habría sido aún mejor si esta función no fuera parte de la clase request_parser - en su lugar, debería haber sido (posiblemente en un espacio de nombres) una función libre en el archivo .cpp.

 2
Author: Frerich Raabe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-22 20:14:34

El punto no es donde se utiliza. La pregunta es qué usa. Si su definición no usa ningún miembro no estático, haría la función estática, de acuerdo con el mismo principio que no pasaría un parámetro redundante a ninguna función (a menos que fueran a ser utilizados en la resultante de sobrecarga)

 0
Author: Armen Tsirunyan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-22 20:15:41