Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - eferion

#561
Cita de: amchacon en 14 Abril 2014, 11:19 AM
Bueno los maps es otra liga, en el vector no pasa eso.

Pero tampoco controla el indice que le metes, lo cual puede ser bueno si quieres máxima eficiciencia pero por otro lado...

Cierto, yo a veces hecho de menos contenedores un poco más "inteligentes" en este aspecto integrados en la stl. A veces es necesario reinventar la rueda.

Cita de: amchacon en 14 Abril 2014, 11:19 AM
Después de este error, he perdido mi confianza en los [] ;D

Jajajaja. No hace falta ser tan derrotista... el operador [] está muy bien... siempre y cuando no ser pierda de vista las implicaciones que tiene ( lo cual suele ser complicado ) XD

Cita de: amchacon en 14 Abril 2014, 11:19 AM
No sé porque la gente odia tanto las excepciones de verdad, es una magnifica forma de depurar.

Pones throw "mensaje" en potenciales errores (archivo no encontrado, entrada invalida...) y envuelves las llamadas a las funciones con un try/catch. Si cualquiera de esas funciones tienen algún error, lo sabras enseguida, sin tener que comprobar funcion por función.

Totalmente de acuerdo, pero también es cierto que es sencillo sentirse tentado a "abusar" del sistema y tirar siempre por el camino de las excepciones aún cuando no vienen a cuento.

Para mí una excepción debe lanzarse cuando la función no es capaz por sí misma de recuperar el error ( la conexión con la base de datos se ha cerrado, no se puede abrir un fichero, no hay privilegios para ejecutar una orden... ). Pero hay otras muchas cosas que no es necesario airear o que, directamente, es mejor diseñarlas de otra forma.

Además, no hay que olvidar que con un buen mecanismo de excepciones se puede extraer muchísima información útil. Pero como todo, es muy importante saber cuándo utilizarlas.

Cita de: amchacon en 14 Abril 2014, 11:19 AM
A ver si te sigo... ¿Algo así?
Código (cpp) [Seleccionar]
map<int,int> Ejemplo;
//...

auto it = Ejemplo.find(4);

if (it != Ejemplo.end()) cout<<it->second<<endl;
else cout<<"No encontrado"<<endl;


No esta mal ^^

Es un ejemplo muy gráfico e ilustrativo. Si bien tienes que añadir algo más de código y éste resulta algo más feo tiene algunas ventajas que, dependiendo del entorno, pueden ser bastante importantes:

* Consume menos memoria ( si sustituyes el segundo int del mapa por un objeto, evitas crear una instancia del mismo de forma innecesaria )... por este mismo motivo este mecanismo puede resultar incluso más rápido.

* Evitas llenar el mapa con guarrería ( a veces interesa tener en el mapa únicamente elementos con valor real ).

* Puedes incluir el código en un método "const".

* Puedes realizar acciones alternativas para el caso de que el índice no se encuentre sin añadir código adicional ( ya tienes que poner un if para comprobar el iterador )
#562
El problema de los corchetes es que si el índice no existe, el contenedor puede añadirlo automáticamente al hacer la consulta ( en los mapas al menos es así ).

Código (cpp) [Seleccionar]

#include <iostream>
#include <map>

int main( )
{
  std::map< int, int > datos;

  std::cout << datos.size( ) << std::endl;

  int numero = datos[ 3 ];

  std::cout << datos.size( ) << std::endl;
}


Una opción es usar, como has comentado, el método "at", que es de solo lectura. El problema es que te obliga a controlar las excepciones y en algunos entornos está mal visto.

El segundo método es lanzar un find para saber si posee ese índice ( en el caso de los vectores se puede hacer con size acordándose de controlar números negativos ) y, si el índice existe entonces recuperar el valor asociado.

#563
No se, no termino de ver tu sistema:

* ¿Te has planteado cómo validar "números"? En el caso de números en coma flotante vas a tener en cuenta la precisión decimal o conviertes sin más ? el resultado no va a ser el mismo.

* ¿ Y qué va a suceder con el comando de "pegar" de la consola ?

Utilizar un sistema "normal" de entrada de datos suele dar menos problemas:

* El sistema está sobradamente probado, por lo que aseguras su funcionamiento.

* Es lo que espera un usuario estándar, por lo que tendrá menos problemas para usarlo.

* Dar un mensaje de error suele ser más explicativo que no dejar que se introduzca un carácter.

* Puedes dar una cobertura más uniforme a lenguajes no contemplados por la tabla ASCII

De hecho, la inmensa mayoría de las aplicaciones en modo consola ( incluso aquellas que tienen una "interfaz gráfica" emulada desde la consola ) te permiten introducir cualquier cosa y te la validan al pulsar el enter o al "cambiar" de input.
#564
Cierto... es hora de hacer un descanso antes de que me explote la cabeza
#565
Sin código es complicado corregir errores... podemos ser buenos, pero no hemos llegado a dominar la telekinesia ( al menos yo ).
#566
Si compilas en Debug, desde luego no van a ser inline porque no se aplicarán optimizaciones... por otro lado, breakpoints en memoria, estoy seguro que muchísima gente no sabe utilizarlos o, directamente, no sabe que existen.
#567
Cita de: amchacon en 10 Abril 2014, 12:41 PM
Si cambias el tipo de la coordenada de int a float (o añades algún método/operador nuevo)... ¿No tendrías que recompilar todo el código? Para que te coja la declaración de la clase digo.

Es que eso no es un chequeo u operación adicional... eso es un cambio de variable directamente.

Yo me refería a, por ejemplo, tener que añadir una comprobación para evitar coordenadas con valores negativos, o limitar el número de decimales, en el caso del tipo float, para evitar "oscilaciones" debido a la falta de precisión.

#568
Estamos encantados de ayudarte... que tienes hecho??
#569
Cita de: amchacon en  9 Abril 2014, 18:29 PM
Vaya no lo había visto así. ¿Pero es necesario el encapsulamiento en un objeto así?

En el caso concreto de las coordenadas no hay mucha diferencia... Sin embargo me gustaría matizar un detalle:

* Si cambias la implementación de la función, sin cambiar la firma, únicamente necesitas recompilar la clase para que todo siga funcionando.

* Si expones la variable directamente y después necesitas cambiarlo a función porque te das cuenta de que necesitas realizar algún chequeo u operación adicional, te ves obligado a recompilar todo el código ( en mi caso unas 6 horas ).

* Los getters y los setters pueden ser convertidos a inline por el compilador, por lo que tendrían exactamente el mismo rendimiento que exponer la variable directamente.

Por ese motivo a mí me gusta más la tercera opción... pero creo que es también cuestión de costumbre.

Cita de: ivancea96 en  9 Abril 2014, 18:04 PM
No es necesario controlarlos con una clase. Es más: se hace más engorroso poner coord.getX() que poner coord.x.

también puedes declarar la clase tal que:

Código (cpp) [Seleccionar]

class Coord
{
  public:
    int X( ) const;
    void X( int x );

    int Y( ) const;
    void Y( int y );

    void SetValues( int x, int y );
};


Tampoco hay demasiada diferencia entre poner coord.X( valor ) y coord.X = valor.

Por otro lado, si es cierto que estaría genial que en alguna revisión incorporasen el concepto de propiedades a C++... reconozco que el uso del operador = es más intuitivo.

También recordar que gracias a la sobrecarga de operadores, es posible "linealizar" este tipo de estructuras para poder acceder a sus elementos de forma secuencial:

Código (cpp) [Seleccionar]

class Coord
{
  public:
    int X( ) const;
    void X( int x );

    int Y( ) const;
    void Y( int y );

    int& operator[]( int index ) const
    {
      int to_return = 0;

      if ( index == 0 )
        to_return = x;
      else if ( index == 1 )
        to_return = y;

      return to_return;
    }
};


Otra ventaja importante de usar getters y setters es que se pueden poner breakpoints en los mismos... mientras que para los accesos directos a variables esto es imposible.
#570
Cita de: Eternal Idol en  9 Abril 2014, 17:33 PM
La segunda manera tambien usa un objeto, en C++ las estructuras son a todos los efectos clases con sus miembros y clases bases publicos por defecto. Los constructores no existen en C.

Ya, lo que sucede es que en las estructuras, por defecto, sus miembros son públicos, lo que viola el concepto de encapsulamiento.

Además en C++ la gente espera encontrar clases... es más natural. Las estructuras, en los grupos en los que he estado, se reservan para tareas específicas, por ejemplo, para cuando hay que enviar tramas de datos por red... aunque hay que tener cuidado de no tener estructuras con herencia para no enviar basura.