c++ - usar - ¿Para qué sirven las funciones privadas de miembros estáticos?
variable static c# (5)
Estaba viendo el analizador de solicitudes del ejemplo de boost :: asio y me preguntaba por qué las funciones de miembro privado como is_char()
son static
. :
class request_parser
{
...
private:
static bool is_char(int c);
...
};
Se usa en el consume función 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 llama a is_char()
. Entonces, ¿hay alguna razón por la cual estas funciones son estáticas?
Entonces, ¿hay alguna razón por la cual estas funciones son estáticas?
Las funciones miembro no static
tienen un parámetro oculto adicional llamado this
. Pasar esto no es gratis, por lo que hacer una función private
static
se puede ver como un medio de optimización .
Pero también se puede ver como un medio para expresar sus requisitos / diseño en su código : si esa función no necesita referirse a ningún dato miembro de la clase, ¿por qué debería ser una función miembro no static
?
Sin embargo, cambiar el tipo de cualquier función miembro, public
o private
, static
o no, requerirá que todos los clientes recompilen. Si esto tiene que 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 nombre sin nombre en el archivo de implementación .
El punto no está donde se usa. La pregunta es qué usa. Si su definición no utiliza ningún miembro no estático, haría la función 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 utilicen en una consecuencia de sobrecarga)
Es estático, ya que no requiere acceso a ninguna variable miembro de los objetos request_parser
. Por lo tanto, hacer que sea 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 formara parte de la clase request_parser
en absoluto; en cambio, debería haber sido (posiblemente en un espacio de nombres) una función gratuita en el archivo .cpp
.
Esta función podría haberse hecho fácilmente independiente, ya que no requiere un objeto de la clase para operar dentro. Convertir una función en miembro estático de una clase en lugar de una función gratuita ofrece dos ventajas:
- Le 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;
- Asocia la función con la clase de una manera similar a un espacio de nombres.
En este caso, parece que solo se aplica el segundo punto.
Para este ejemplo específico, la elección de un static is_char()
es probablemente una documentación. La intención es impresionarte de que el método is_char()
no está is_char()
a una instancia específica de la clase, sino que la funcionalidad es específica de la clase misma .
En otras palabras, al hacerlo static
, dicen que is_char()
es una especie de función de utilidad ... una que se puede usar independientemente del estado de una instancia determinada. Al hacerlo private
, dicen que usted (como cliente) no debe tratar de usarlo. O no hace lo que crees que es, o se implementa de una manera muy limitada y controlada.
La respuesta de @Mark Ransom presenta 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 aprobada de un objeto instanciado.
Una aplicación común de esto es abstraer una implementación pthread de una manera orientada a objetos. La función de hilo debe ser estática, pero declararla privada limita el acceso de esa función a la clase (a todos menos a los más determinados). El hilo se 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();
}
...