2011-01-18 16 views
12

Después de leer las respuestas de sbi y Eli Bendersky en this question empecé a preguntarme para qué sirven las funciones de miembro estático.Funciones de miembro estático

La función de amigo libre de una clase no debería poder hacer cualquier cosa que una función de miembro estática puede hacer? Si es así, ¿por qué/cuándo debería preferir una función de miembro estático a una de amigo libre?

+0

A menudo, francamente, no deberías. –

Respuesta

12

En general:

requieren el acceso a los miembros privados

métodos estáticos tienen acceso a los miembros privados de la clase. Si lo necesita, puede usar una función miembro estática. Debes declararlo en el encabezado de todos modos para darle acceso, por lo que puedes convertirlo en un miembro en lugar de un amigo. Se suele hacer de esta manera para los singletons que tienen un método getInstance() como singleton, y para las clases que usan un método de fábrica estático createInstance() para garantizar que se crean en el montón. Ambos necesitan acceso al constructor privado.

Meta-programación

métodos estáticos son muy buenos para la plantilla de meta-programación donde se puede pasar en una clase y llamar a su método sin saber en el momento de la llamada función de lo que realmente va a conseguir invocado. Esto se conoce comúnmente como "polimorfismo en tiempo de compilación" y es una parte importante de la metaprogramación. std :: char_traits se basa en este principio.

acceso restringido

El uso común de una función miembro estática privada, a fin de que sólo se puede acceder por la clase, y no en sí necesitan tener acceso a los miembros privados, no es un buen uso de funciones miembro estáticas porque es parte de los detalles de implementación de la clase, y esto se realiza mejor en el espacio de nombres anónimo de la unidad de compilación.

Sin embargo, si la función de miembro estático es protected tiene uso, ya que puede ser llamado por clases derivadas pero no por clases externas.

funciones friend

  • puede tener acceso a los miembros privados, sino que tenga que ser declarada en la cabecera de todos modos.
  • Se puede utilizar en la metaprogramación como parte de una "sobrecarga", sin embargo, aún debe declararse en el encabezado. (El ejemplo común es operator<<)
  • No funciona para el acceso protegido con amistad, ya que lo que se intenta hacer aquí es restringir el acceso al método, no a qué tiene acceso la llamada.
+0

¿En qué casos las funciones de amigo libre no se pueden usar en la meta-programación de plantillas? No se puede encontrar ningún ejemplo en el que una función libre de amigos con plantillas no pueda hacer algo que una función miembro estática puede hacer. El tercer punto es bueno, ¡no pensé en eso! – peoro

+0

clases de rasgos, por ejemplo. traits_class :: dostuff (params); dostuff es un miembro estático de traits_class. – CashCow

+0

En la respuesta anterior, traits_class es un parámetro de plantilla o derivado de un parámetro de plantilla. – CashCow

4

A menudo, francamente, no debería. Las funciones gratuitas son ampliamente infravaloradas.

El "espacio de nombre" implícito que obtiene al usar un miembro estático (pretendiendo que la clase no es más que un espacio de nombre para el miembro estático, que es cierto) es el único beneficio que se me ocurre.

Si el miembro de la función estática necesita variables persistentes, la capacidad de tener miembros de datos estáticos junto con ella también puede ser útil.

+0

+1 para "Las funciones gratuitas están muy subestimadas." –

10

Los métodos estáticos:

  • Proporcionar encapsulación en el "espacio de nombres" creado por la clase. Si su clase es Animal y el método estático es Create, debe llamarlo al Animal::Create. Esto es mejor que las funciones globales, y permite implementar fábricas y "constructores virtuales" con sintaxis relativamente natural.
  • Tiene acceso a miembros estáticos. Dichos miembros son útiles en algunos casos, y sin métodos y miembros estáticos tendrías que usar variables y funciones globales.
+1

Además, si se les da una instancia de la clase, también tienen acceso a todos los métodos y funciones privados. Esto es muy útil. – Macke

+0

Los miembros de la clase estática también son visibles en las funciones gratuitas, y una función sin amigos puede acceder al método no público Tienes razón sobre el primer punto, pero es solo una cuestión de sintaxis, ¿no? ¿No contrasta esto con lo dicho en la otra pregunta? – peoro

+0

@ peoro: (1) se trata principalmente del espacio de nombres, sin sintaxis. Es conveniente tener un método estático * dentro * de una clase. De lo contrario, ¿cómo se relaciona con el usuario que es parte de la clase lógicamente? Una vez que tiene (1), los miembros estáticos son mucho más convenientes y "normales" forma de acceder a los miembros estáticos que tener funciones globales y declararlos amigos dentro de la clase, en mi humilde opinión. –

3

Algunas personas son cautelosas con el uso de funciones estáticas porque a menudo las utilizan aquellos que provienen de un entorno de procedimientos y no comprenden OO.

Sin embargo, hay muchos patrones de diseño que tienen sentido para ser implementado utilizando métodos estáticos

Por ejemplo. Los patrones de Singleton y Factory para nombrar un par de cosas de mi cabeza, de hecho, la mayoría de los patrones estructurales que requieren la creación de objetos requerirían funciones de miembros estáticos.

+1

sí, las funciones estáticas se usan para este propósito, pero las funciones de amigo deberían poder hacer lo mismo sin ninguna desventaja ... – peoro

+0

Pero también tenga cuidado con los datos globales que se disfrazan a través de un singleton. Consulte la rica discusión sobre SO aquí: http://stackoverflow.com/questions/137975/... - rholmes acaba de editar – rholmes

1

No hay ningún valor añadido a las funciones de miembro static, como ha identificado correctamente. Peor aún, cuando se usa para detalles de implementación, esto introduce dependencias adicionales (en términos de compilación).

La única uso que no podía ser emulado con un sin función anónima, es el protected acceso, es decir, una clase derivada para acceder a una función estática de los padres. Sin embargo, esto nunca es necesario: puedes simplemente convertirlo en una función miembro regular (supongo que no tienes estado global, de lo contrario la distinción estática/amiga no es de interés inmediato).

Se ha invocado el uso de las funciones static en la metaprogramación de plantillas ... sin embargo, es muy similar al problema de los tipos internos: hace que sea difícil proporcionar una versión predeterminada. Por otra parte, una función gratuita adecuadamente definido (que toma el tipo como un puntero), puede proponer una versión de la plantilla:

struct some_traits 
{ 
    static void doStuff(); 
}; 

// versus 

struct some_traits {}; 

void doStuff(some_traits*); 

// and the default: void doStuff(...); 

Y, por supuesto, siempre existe la pregunta de por qué esto debería ser una función estática , cuando una función miembro proporcionaría más flexibilidad al usuario. En este sentido, citaré el movimiento que hizo el Comité Estándar con el concepto Allocator: los asignantes con estado ahora están autorizados, lo que nos da la oportunidad de agrupar los nodos de un dado map en una misma página en lugar de distribuirlos por todo el montón.

Finalmente, existe la interfaz problema. Sin embargo, hace mucho tiempo que Sutter abogó por que una clase y las funciones gratuitas definidas en el mismo encabezado constituyesen la interfaz pública de esta clase => ¡para eso es ADL! Entonces, es más algo para consolar a los antiguos programadores de OO que una "buena práctica".

Realmente, no veo ningún beneficio al utilizar las funciones de miembro static. Me gustaría que la gente piense lo contrario para proponer casos reales.

Cuestiones relacionadas