¿Es una buena idea proporcionar diferentes firmas de funciones que hagan lo mismo?

23

Aquí hay una clase de C ++ que se construye con tres valores.

class Foo{

    //Constructor
    Foo(std::string, int, char);

private:
    std::string foo;
    char bar;
    int baz;
};

Todos los tipos de parámetros son diferentes.
Podría sobrecargar el constructor para que el orden no importe.

class Foo{

    //Constructors
    Foo(std::string, char, int);
    Foo(std::string, int, char);
    Foo(char, int, std::string);
    Foo(char, std::string, int);
    Foo(int, std::string, char);
    Foo(int, char, std::string);


private:
    std::string foo;
    char bar;
    int baz;
};

¿Pero es una buena idea?
Empecé a hacerlo porque sabía qué cosas necesitaba una clase / función;
No siempre recordé en qué orden los tomó.


He estado asumiendo que el compilador optimiza esto como si llamara al mismo constructor.

//compiler will implement this with the same code? 
//maybe not.. I could call a function to get a parameter, 
//and that function could change the state of the program, before calling
//a function to get another parameter and the compiler would have to
//implement both
Foo foo1("hello",1,'a');
Foo foo2('z',0,"world");

¿Cuáles son sus opiniones sobre sobrecargar una función para que el orden no importe?


Además, si estoy escribiendo algunas funciones de utilidad,
¿es una buena idea proporcionar diferentes nombres de funciones que hagan lo mismo?

p.ej.

void Do_Foo();
void DoFoo();
void do_foo();
//etc..

No veo a menudo estas dos convenciones pero similares.
¿Debo romper o abrazar el hábito?

Trevor Hickey
fuente
1
Uno solo debería hacer un esfuerzo para proporcionar múltiples formas de expresar algo si cada forma explícitamente proporcionada en algunos casos será clara e inequívocamente superior a cualquiera de las otras. Eso no significa que, en general, se deba hacer un esfuerzo para garantizar que algo solo se pueda escribir en una forma canónica, pero no tiene sentido realizar un esfuerzo que permita especificar algo de alguna manera que no sea la mejor.
supercat
Una especie de duplicado de mi pregunta aquí (ahora estoy de acuerdo en que es una mala idea).
Leftaroundabout

Respuestas:

93

Podría sobrecargar el constructor para que el orden [de los parámetros] no importe ... ¿Pero es una buena idea?

No.

Tener diferentes sobrecargas del constructor tendrá el efecto opuesto de lo que pretendes. El programador que viene después de que usted espera que diferentes sobrecargas tengan un comportamiento diferente, y le preguntará: "¿Qué tipo de comportamiento diferente está expresando cada una de estas sobrecargas?

La mayoría de los programadores esperan la disciplina de tener parámetros de método en un orden predefinido, y herramientas como IntelliSense les indicarán el orden esperado de los parámetros a medida que los ingresen.


Tener múltiples nombres de funciones que hacen lo mismo es el mismo problema; Los programadores esperan que las variantes tengan un comportamiento diferente. Una función o método por comportamiento, por favor, y simplemente adopte un patrón de nomenclatura consistente.

Robert Harvey
fuente
14
muchos votos positivos. Me detendré de inmediato. gracias.
Trevor Hickey
8
Además, no puede nombrar a los constructores de manera diferente para explicar su propósito, los lectores tienen que inferirlo de los parámetros. Sobrecargar el constructor de esta manera hace que sea mucho más difícil de entender.
Zachary Yates
3
"Tener múltiples nombres de funciones que hacen lo mismo ..." - para un "buen" momento, mire las clases de Ruby String Hash Array File .
+1. Estás tratando con desarrolladores / programadores. La idea de Microsoft de "el usuario es mono" no funciona aquí.
Manoj R
1
@ZacharyYates La falta de "nombres de constructor" se puede solucionar exponiendo métodos de construcción estáticos. Esta es una práctica estándar en Java, aunque no tanto en C ++.
Xion
14

A veces es necesario apoyar la conmutación entre argumentos. Por ejemplo:

double operator *(int, double);
double operator *(double, int);

No queremos multiplicar an inty doublecalcular algo diferente si los operandos se invierten. ¡Tampoco queremos obligar a los programadores a recordar que al multiplicar intsy doubles, el doubleva a la izquierda!

No importa que este sea un operador porque lo mismo se aplica a:

footype plus(const footype &, const bartype &);
footype plus(const bartype &, const footype &);

Realmente depende del tipo de función. Mientras que la mayoría de los programadores probablemente quieren soporte para la conmutatividad en las bibliotecas aritméticas, no necesariamente quieren, digamos, una función de biblioteca de E / S para soportar todos los posibles órdenes de argumentos.

La preocupación probablemente depende de la anidación esperada en la que las llamadas de función van a estar involucradas. La flexibilidad en los operadores aritméticos nos permite cambiar la estructura general del árbol de sintaxis para aclarar la expresión general: agrupar términos similares y similares.

Kaz
fuente