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

6 minutos de lectura

yo estaba mirando el solicitar analizador del ejemplo boost::asio y me preguntaba por qué el miembro privado funciona 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 is_char() y ninguna función de miembro estático está llamando is_char(). Entonces, ¿hay alguna razón por la que estas funciones sean estáticas?

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

  1. Da acceso a la función 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 manera similar a un espacio de nombres.

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

  • De hecho, ese # 1 lo olvidé en mi respuesta. +1 de mí también.

    – sbi

    22 de junio de 2011 a las 20:44


  • Si una función miembro estática toma una instancia de esa clase como argumento, ¿no es conceptualmente una función miembro no estática?

    –Oliver Charlesworth

    22 de junio de 2011 a las 22:24

  • @Oli: Sí, básicamente hiciste el this puntero explícito en los argumentos.

    – Frerich Raabe

    23 de junio de 2011 a las 7:30

  • +1 para la primera viñeta, olvidé esto. Una adición: también le da acceso a la función a miembros privados y protegidos de la propia clase (léase: variables estáticas con visibilidad privada o protegida).

    – Frerich Raabe

    23 de junio de 2011 a las 7:31

  • @Mark Ransom ¿Podría mostrarme un ejemplo simple para entender completamente eso #1?

    – John

    10 de mayo a las 1:51


avatar de usuario
sbi

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

No-static Las funciones miembro tienen un parámetro adicional oculto llamado this. Aprobar esto no es gratis, así que hacer una private función static puede ser visto como un medio de mejoramiento.
Pero también puede ser visto como un medio de expresando 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 ser una no-static función miembro?

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

  • +1 para el último párrafo: “Si es necesario hacer esto para una función privada que esos clientes nunca pueden usar, es una pérdida de recursos. Por lo tanto, generalmente muevo tantas funciones como sea posible de las partes privadas de la clase a una sin nombre espacio de nombres en el archivo de implementación”. En general, uno debe esconder entidades en la caja de encapsulación más pequeña posible. Los métodos privados y los miembros de datos no son accesibles para ningún cliente fuera de la clase, nunca entendí por qué tienen que declararse en el encabezado de la clase … pero estoy divagando

    – Laryx Decidua

    10 de septiembre de 2020 a las 12:44

  • @LaryxDecidua: la búsqueda de nombres haría cosas extrañas si diferentes archivos vieran que una clase tiene un conjunto diferente de miembros.

    – Davis arenque

    7 de enero a las 1:37

avatar de usuario
delfín

Para este ejemplo específico, la elección de un static is_char() es muy probable que sea de documentación. La intención es recalcarles que el is_char() El método no está restringido a una instancia específica de la clase, pero la funcionalidad es específico de la clase en sí.

En otras palabras, al hacerlo static ellos estan diciendo eso is_char() es una especie de función de utilidad … una que se puede usar independientemente del estado de una instancia dada. al hacerlo private, dicen que usted (como cliente) no debe intentar usarlo. O 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 de 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 de alguna manera orientada a objetos. Su función de subproceso 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 subproceso se le puede pasar una instancia de la clase en la que se está “ocultando” y ahora tiene acceso para realizar la lógica utilizando los datos del 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();
}
...

  • arg->getThisObjectsData() debiera ser thisObj->getThisObjectsData() ?

    – rve

    23 de junio de 2011 a las 7:42

  • @rve ¿Qué quiere decir con “a todos menos a los más decididos”? ¿Podría por favor explicarme eso?

    – John

    10 de mayo a las 6:16


  • @John Declarar algo privado limita la accesibilidad de esa función a la clase, pero si está lo suficientemente determinado, aún puede acceder a funciones privadas desde otro lugar. Sin embargo, eso sería un truco feo que nadie debería hacer en el código de producción.

    – rve

    24 de mayo a las 18:21


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

Por lo que vale, hubiera sido incluso mejor si esta función no fuera parte del request_parser clase en absoluto; en cambio, debería haber sido (posiblemente en un espacio de nombres) una función libre en el .cpp expediente.

el punto no es dónde esta usado. La pregunta es qué usa. Si su definición no usa ningún miembro no estático, haría que la función fuera estática, de acuerdo con el mismo principio de que no pasaría un parámetro redundante a ninguna función (a menos que se usaran en un resultado de sobrecarga)

¿Ha sido útil esta solución?