c++ - estaticos - Espacio de nombres+funciones versus métodos estáticos en una clase
miembros estaticos c++ (7)
Debe usar un espacio de nombres, porque un espacio de nombres tiene muchas ventajas sobre una clase:
- No tienes que definir todo en el mismo encabezado.
- No necesita exponer toda su implementación en el encabezado.
- No puedes
using
un miembro de la clase; puedesusing
un miembro del espacio de nombres - No puedes
using class
, aunqueusing namespace
no es tan a menudo una buena idea - Usar una clase implica que hay algún objeto que se crea cuando realmente no hay ninguno
Los miembros estáticos son, en mi opinión, muy usados en exceso. No son una necesidad real en la mayoría de los casos. Las funciones de los miembros estáticos probablemente se encuentran mejor que las funciones de alcance de archivos, y los miembros de datos estáticos son solo objetos globales con una reputación mejor y no merecida.
Digamos que tengo, o voy a escribir, un conjunto de funciones relacionadas. Digamos que están relacionados con las matemáticas. Organizativamente, debería yo:
- Escriba estas funciones y colóquelas en mi espacio de nombres
MyMath
y consúltelas a través deMyMath::XYZ()
- Cree una clase llamada
MyMath
y haga que estos métodos sean estáticos y refiérase aMyMath::XYZ()
similar
¿Por qué elegiría uno sobre el otro como un medio para organizar mi software?
Hay muchas personas que no estarían de acuerdo conmigo, pero así es como lo veo:
Una clase es esencialmente una definición de un cierto tipo de objeto. Los métodos estáticos deben definir operaciones que están íntimamente ligadas a esa definición de objeto.
Si solo va a tener un grupo de funciones relacionadas no asociadas con un objeto subyacente o la definición de un tipo de objeto , entonces diría que ir solo con un espacio de nombres. Sólo para mí, conceptualmente, esto es mucho más sensato.
Por ejemplo, en su caso, pregúntese, "¿Qué es una MyMath?" Si MyMath
no define un tipo de objeto, entonces diría: no lo conviertas en una clase.
Pero como dije, sé que hay muchas personas que (incluso con vehemencia) no estarían de acuerdo conmigo en esto (en particular, los desarrolladores de Java y C #).
Preferiría los espacios de nombres, de esa manera puede tener datos privados en un espacio de nombres anónimo en el archivo de implementación (para que no tenga que aparecer en el encabezado en lugar de miembros private
). Otro beneficio es que al using
su espacio de nombres, los clientes de los métodos pueden optar por no especificar MyMath::
Tanto el espacio de nombres como el método de clase tienen sus usos. El espacio de nombres tiene la capacidad de distribuirse a través de los archivos; sin embargo, eso es una debilidad si necesita hacer que todos los códigos relacionados vayan en un solo archivo. Como se mencionó anteriormente, la clase también le permite crear miembros estáticos privados en la clase. Puede tenerlo en el espacio de nombres anónimo del archivo de implementación, sin embargo, todavía tiene un alcance mayor que tenerlos dentro de la clase.
Una razón más para usar la clase - Opción para hacer uso de los especificadores de acceso. Entonces, posiblemente puedas dividir tu método estático público en métodos privados más pequeños. Método público puede llamar a múltiples métodos privados.
Por defecto, use las funciones de espacio de nombre.
Las clases son para construir objetos, no para reemplazar espacios de nombres.
En código orientado a objetos
Scott Meyers escribió un artículo completo para su libro Effective C ++ sobre este tema, "Prefiera las funciones que no sean miembros no amigos a las funciones miembro". Encontré una referencia en línea a este principio en un artículo de Herb Sutter:
Lo importante es saber que: En C ++, las funciones en el mismo espacio de nombres que una clase pertenecen a la interfaz de esa clase (porque ADL buscará esas funciones cuando resuelva las llamadas a funciones).
Las funciones de espacio de nombres, a menos que se declaren "amigos", no tienen acceso a las partes internas de la clase, mientras que los métodos estáticos sí lo tienen.
Esto significa, por ejemplo, que al mantener su clase, si necesita cambiar las partes internas de su clase, deberá buscar efectos secundarios en todos sus métodos, incluidos los estáticos.
Extensión I
Agregar código a la interfaz de una clase.
En C #, puede agregar métodos a una clase incluso si no tiene acceso a ella. Pero en C ++, esto es imposible.
Pero, aún en C ++, aún puede agregar una función de espacio de nombre, incluso a una clase que alguien escribió para usted.
Vea desde el otro lado, esto es importante al diseñar su código, ya que al colocar sus funciones en un espacio de nombres, autorizará a sus usuarios a aumentar / completar la interfaz de la clase.
Extensión II
Como efecto secundario del punto anterior, es imposible declarar métodos estáticos en múltiples encabezados. Todos los métodos deben ser declarados en la misma clase.
Para los espacios de nombres, las funciones del mismo espacio de nombres se pueden declarar en varios encabezados (la función de intercambio casi estándar es el mejor ejemplo de eso).
Extensión III
La importancia básica de un espacio de nombres es que en algún código, puede evitar mencionarlo, si usa la palabra clave "usar":
#include <string>
#include <vector>
// Etc.
{
using namespace std ;
// Now, everything from std is accessible without qualification
string s ; // Ok
vector v ; // Ok
}
string ss ; // COMPILATION ERROR
vector vv ; // COMPILATION ERROR
E incluso puede limitar la "contaminación" a una clase:
#include <string>
#include <vector>
{
using std::string ;
string s ; // Ok
vector v ; // COMPILATION ERROR
}
string ss ; // COMPILATION ERROR
vector vv ; // COMPILATION ERROR
Este "patrón" es obligatorio para el uso adecuado del idioma de intercambio casi estándar.
Y esto es imposible de hacer con métodos estáticos en las clases.
Entonces, los espacios de nombres de C ++ tienen su propia semántica.
Pero va más allá, ya que puedes combinar los espacios de nombres de una manera similar a la herencia.
Por ejemplo, si tiene un espacio de nombres A con una función AAA, un espacio de nombres B con una función BBB, puede declarar un espacio de nombres C y colocar AAA y BBB en este espacio de nombres con la palabra clave usando.
Conclusión
Los espacios de nombres son para espacios de nombres. Las clases son para las clases.
C ++ fue diseñado para que cada concepto sea diferente y se use de manera diferente, en diferentes casos, como solución a diferentes problemas.
No uses clases cuando necesites espacios de nombres.
Y en tu caso, necesitas espacios de nombres.
- Si necesita datos estáticos, utilice métodos estáticos.
- Si son funciones de plantilla y le gustaría poder especificar un conjunto de parámetros de plantilla para todas las funciones juntas, utilice métodos estáticos en una clase de plantilla.
De lo contrario, utilice las funciones de espacio de nombres.
En respuesta a los comentarios: sí, los métodos estáticos y los datos estáticos tienden a ser sobreutilizados. Es por eso que ofrecí solo dos escenarios relacionados donde creo que pueden ser útiles. En el ejemplo específico del OP (un conjunto de rutinas matemáticas), si quisiera la capacidad de especificar parámetros, por ejemplo, un tipo de datos centrales y una precisión de salida, que se aplicaría a todas las rutinas, podría hacer algo como:
template<typename T, int decimalPlaces>
class MyMath
{
// routines operate on datatype T, preserving at least decimalPlaces precision
};
// math routines for manufacturing calculations
typedef MyMath<double, 4> CAMMath;
// math routines for on-screen displays
typedef MyMath<float, 2> PreviewMath;
Si no necesita eso, entonces use un espacio de nombres.