2010-06-18 17 views
5

Pero no sé si debería usar métodos estáticos, solo un encabezado, una clase o algo más.C++: ¿Cómo diseñar una clase de utilidad?

¿Cuál sería la mejor práctica? Pero, no quiero tener una instancia de una clase de utilidad.

Quiero añadir funciones como:

Uint32 MapRGB (int r, int g, int b); 
const char* CopyString(const char* char); 
// etc. You know: utility methods... 
+2

CopyString() parece sospechoso: ¿qué hará? –

+0

@Neil: Copiando una cadena al montón, para que no se salga del alcance ... –

+8

No lo haga, bajo ninguna circunstancia, es una fuga de memoria casi garantizada. Use std :: string. –

Respuesta

21

No ponerlos en una clase; simplemente conviértelos en funciones no miembro en el ámbito del espacio de nombres.

No existe una regla que diga que cada función tiene que ser una función miembro de alguna clase.

+0

@James: Ah, un espacio de nombres. Tal vez no está mal ... ¿Puedes dar un pequeño ejemplo de código? –

+0

Algunas tiendas prefieren clases sobre espacios de nombres porque es más 'java'. * suspiro * –

+3

@Martijn: recomendaría obtener uno de los libros introductorios que se enumeran en [La guía y la lista definitivas de libros en C++] (http://stackoverflow.com/questions/388242/the-definitive-c-book-guide -y-lista). Efectivamente, el código puede ser tal como lo muestra en su pregunta, y si lo desea o lo necesita, puede colocar las funciones en un espacio de nombre. –

1

Probablemente no haya ninguna razón para tener una clase para envolver estas funciones si no pertenecen lógicamente a una clase. En ese caso, puede hacer que sean funciones gratuitas. Podría ser apropiado contenerlos en un espacio de nombres para ayudar a evitar colisiones de nombres.

Si desea proporcionar una agrupación lógica de stringer de las clases, no hay ningún daño real al tenerlas como funciones estáticas miembro de una clase, pero no veo ninguna razón por la que tenga funciones como MapRGB() y CopyString(). miembros de la misma clase.

3

Un factor es si incluso ponerlos en una clase, o simplemente ponerlos como nomembers en un espacio de nombres (en Java, tendría que utilizar una clase, pero C++ ofrece espacios de nombres).

Si lo hace un miembro de la clase, la decisión más importante que debe tomar sobre cada función es si requeriría o debería afectar a cualquier estado que no se reciba o pase a través de sus parámetros y valor de retorno. Si no es así, entonces debe hacerse static, ya que no usará el argumento oculto "this".

Un argumento para utilizar una clase en lugar de un espacio de nombres es si su clase de utilidad puede necesitar invocar métodos adicionales para su implementación (por ejemplo, en caso de recurrencia, cálculos complejos, etc.). A continuación, puede hacer que su método sea static public y todo lo que se implemente sobre static private. Han pasado muchos años desde que utilicé C++, pero no creo que pueda "ocultar" las funciones que no son miembro en un espacio de nombres (alguien me corrige si estoy equivocado).

En términos de diseño de la interfaz de función, tenga en cuenta la cantidad de argumentos. Si hay demasiados argumentos entrantes (especialmente si son de tipos similares y algunos están relacionados), es posible que desee considerar el uso de tipos adicionales en lugar de pasar múltiples argumentos. Por ejemplo, en lugar de calculateVolume(int x, int y, int z), es posible que desee hacer algo como calculateVolume(Point3D). Del mismo modo, en su caso, use una clase RGB. Puede parecer una tontería, pero puede ahorrar algunos errores molestos (por ejemplo, si tiene funciones que toman entradas y RGB), y tiempo (si tiene que pasar los valores a otras funciones). Puede crear un método de fábrica estático para facilitar la creación de estos tipos al pasar argumentos. Por ejemplo: doSomethingWithColor(RGB.create(20,30,40))

+1

+1 - ¡Para señalar una buena respuesta estática! – JonH

+2

Si se implementa una función no miembro en un archivo .cpp, cualquier función que necesite pero que no deba exponerse puede colocarse en un espacio de nombre sin nombre en ese archivo .cpp (o hacerse estático). Es más complicado si tiene plantillas de funciones, ya que su implementación debe estar en el archivo de encabezado en sí, pero generalmente esto se soluciona teniendo un espacio de nombres de "detalles" en el que se usa la funcionalidad no pública. Este es el enfoque que toma gran parte de Boost. –

+0

@James: Gracias James ... – Uri

1

Si solo desea agrupar funciones juntas, pero no crear una instancia del grupo, entonces probablemente debería pensar en ponerlas en un espacio de nombres en lugar de en una clase.

Aunque intentaría utilizar espacios de nombres significativos, poner MapRGB y CopySstring juntos tiene muy poco sentido.Si realmente necesita ambos, y realmente no tiene otras funciones que se ocupen de cadenas o mapeo RGB, ponerlas en un espacio de nombres "utillity" puede tener sentido, pero si las está usando, parece que usted tenga más "cosas" de cuerdas y algo más de "color", y probablemente podría beneficiarse de tener un espacio de nombres para cada una.

1

Generalmente tengo una .a (.lib en windows) llamada "util" que se enlaza. Sin embargo, generalmente una clase "util" es una mala noticia e introduce una dependencia que rompe el diseño orientado a objetos estándar. Ahora, si intenta sacar una clase para volver a utilizarla en un proyecto diferente, tiene miles de dependencias ocultas en su biblioteca de utilidades. Básicamente, es útil, pero haz tu mejor esfuerzo para evitar poner cosas allí.

Cuestiones relacionadas