Digamos que tengo, o voy a escribir, un conjunto de funciones relacionadas. Digamos que están relacionadas con las matemáticas. Organizacionalmente, debería:
- Escribe estas funciones y ponlas en mi
MyMath
espacio de nombres y consúltelas a través deMyMath::XYZ()
- Cree una clase llamada
MyMath
y haga que estos métodos sean estáticos y consulte el mismoMyMath::XYZ()
¿Por qué elegiría uno sobre el otro para organizar mi software?
c++
namespaces
static-methods
RobertL
fuente
fuente
Respuestas:
Por defecto, use funciones de espacio de nombres.
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 eficaz de C ++ sobre este tema, "Prefiero funciones que no sean miembros y no amigos a funciones miembros". Encontré una referencia en línea a este principio en un artículo de Herb Sutter:http://www.gotw.ca/gotw/084.htm
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 al resolver llamadas de función).
Las funciones de espacio de nombres, a menos que se declare "amigo", no tienen acceso a los elementos internos de la clase, mientras que los métodos estáticos sí.
Esto significa, por ejemplo, que al mantener su clase, si necesita cambiar los elementos internos de su clase, deberá buscar los 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 nombres, incluso a una clase que alguien escribió para usted.
Vea desde el otro lado, esto es importante al diseñar su código, porque al poner 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 declararse en la misma clase.
Para 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 frescura básica de un espacio de nombres es que en algún código, puede evitar mencionarlo, si usa la palabra clave "using":
E incluso puede limitar la "contaminación" a una clase:
Este "patrón" es obligatorio para el uso adecuado del lenguaje de intercambio casi estándar.
Y esto es imposible de hacer con métodos estáticos en las clases.
Por lo tanto, los espacios de nombres C ++ tienen su propia semántica.
Pero va más allá, ya que puede combinar espacios de nombres de forma 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 traer 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 clases.
C ++ fue diseñado para que cada concepto sea diferente y se use de manera diferente, en diferentes casos, como una solución a diferentes problemas.
No use clases cuando necesite espacios de nombres.
Y en su caso, necesita espacios de nombres.
fuente
Hay muchas personas que no estarían de acuerdo conmigo, pero así es como lo veo:
Una clase es esencialmente una definición de 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 una definición de un tipo de objeto , entonces diría ir solo con un espacio de nombres. Solo para mí, conceptualmente, esto es mucho más sensato.
Por ejemplo, en su caso, pregúntese: "¿Qué es un MyMath?" Si
MyMath
no define un tipo de objeto, entonces yo diría: no hacen que sea una clase.Pero como dije, sé que hay mucha gente que (incluso con vehemencia) no está de acuerdo conmigo en esto (en particular, los desarrolladores de Java y C #).
fuente
typedef
, usarlos como parámetros de plantilla, etc.De lo contrario, use funciones de espacio de nombres.
En respuesta a los comentarios: sí, los métodos estáticos y los datos estáticos tienden a ser utilizados en exceso. 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 básicos y precisión de salida, que se aplicarían a todas las rutinas, podría hacer algo como:
Si no es necesario que, a continuación, por todos los medios utilizar un espacio de nombres.
fuente
template
argumentos!Debe usar un espacio de nombres, porque un espacio de nombres tiene muchas ventajas sobre una clase:
using
un miembro de la clase; puedesusing
un miembro del espacio de nombresusing class
, aunqueusing namespace
no siempre es una buena ideaLos miembros estáticos son, en mi opinión, muy, muy sobreutilizados. No son una necesidad real en la mayoría de los casos. Las funciones de miembros estáticos probablemente estén mejor como funciones de alcance de archivo, y los miembros de datos estáticos son solo objetos globales con una mejor reputación inmerecida.
fuente
inline
palabra clave para satisfacer ODR.inline
, y NO es "alinear" el cuerpo de una función. El propósito real (y garantizado por el estándar)inline
es evitar múltiples definiciones. Lea sobre "Una regla de definición" para C ++. Además, la pregunta SO vinculada no se estaba compilando debido a problemas de encabezado precompilados en lugar de problemas de ODR.Preferiría 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 los
private
miembros). Otro beneficio es que, porusing
su espacio de nombres, los clientes de los métodos pueden optar por no especificarMyMath::
fuente
Una razón más para usar la clase: opción para hacer uso de los especificadores de acceso. Luego, posiblemente pueda dividir su método estático público en métodos privados más pequeños. El método público puede llamar a varios métodos privados.
fuente
private
método más accesible es más accesible que un método cuyo prototipo no se publica en absoluto en un encabezado (y, por lo tanto, permanece invisible). Ni siquiera estoy mencionando la mejor encapsulación que ofrecen las funciones de espacios de nombres anónimos..cpp
archivo, lo que lo haría privado a esa unidad de traducción sin dar ninguna información superflua a nadie que lea el archivo de encabezado. Efectivamente, estoy tratando de defender el idioma de PIMPL..cpp
archivo si desea usar plantillas.Tanto el espacio de nombres como el método de clase tienen sus usos. El espacio de nombres tiene la capacidad de extenderse a través de los archivos, sin embargo, eso es una debilidad si necesita aplicar todo el código relacionado para ir en un 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, sigue siendo un alcance mayor que tenerlos dentro de la clase.
fuente
private:
propias. y en muchos casos donde parece que se requiere acceso privilegiado , eso se puede factorizar. la función más 'privada' es aquella que no aparece en un encabezado.private:
Los métodos nunca pueden disfrutar de este beneficio.