Pregunta

Estoy trabajando en el código que hace el vecino más cercano de consultas.Hay dos simples ideas que subyacen cómo un usuario puede consultar datos en una búsqueda:

  • más cercana de N puntos a un punto dado en el espacio.
  • todos los puntos dentro de una distancia dada.

En mi código, los Puntos se colocan en una PointList, y el PointList es un recipiente que tiene la tarea de mantener un seguimiento de los puntos que se han encontrado en la búsqueda.

Ahora mi PointList objeto tiene un constructor:

PointList( unsigned int maxvals ); // #1

Los próximos dos constructores que me gustaría añadir son estos:

PointList( float maxdist ); // #2
PointList( unsigned int maxvals, float maxdist ); // #3

Mi pregunta es:¿cómo puedo asegurarme de que mis usuarios y el compilador de C++, se generará el derecho constructor de la PointList y la diferencia entre los constructores de 1 y 2?Debo implementar #3 y constantes que definen arbitraria grandes los valores de maxvals y maxdist?Otra alternativa podría ser escribir otro sistema de objetos ligeros que rigen la lógica para añadir Puntos a la lista, pero que se siente como una exageración de una idea tan simple.

Realmente estoy tratando de hacer esto transparente para los usuarios, que son en su mayoría de los científicos que han aprendido C++, a veces sin el beneficio de la educación formal.Gracias!

¿Fue útil?

Solución

Resolución de sobrecarga para los tipos enteros se realiza en dos categorías, que pueden ser muy groso resume a

  • Promoción:Se trata de una conversión de tipos más pequeños que int a int o unsigned int, dependiendo de si int puede almacenar todos los valores del tipo de fuente.
  • Conversión:Se trata de una conversión de cualquier tipo de entero a otro número entero.

Similar, la conversión de los tipos de punto flotante se realiza en dos categorías

  • Promoción:Se trata de una conversión de float a double
  • Conversión:Se trata de una conversión de cualquier tipo de punto flotante a otro tipo de punto flotante de

Y hay una conversión de entero a flotante o en la espalda.Este es clasificada como una conversión, en lugar de una promoción.Una promoción está clasificado mejor que una conversión, y donde sólo una promoción es necesario, en ese caso será preferido.Por lo tanto, puede utilizar los siguientes constructores

PointList( int maxVals );
PointList( unsigned int maxVals );
PointList( long maxVals );
PointList( unsigned long maxVals );

PointList( double maxDist );
PointList( long double maxDist );

Para cualquier tipo de entero, esto debe seleccionar el primer grupo de constructor.Y para cualquier tipo de punto flotante, esto debe seleccionar el segundo grupo de constructores.El original de las dos constructores podría fácilmente resultar en una ambigüedad entre float y unsigned int, si se pasa un int, por ejemplo.Por el otro, de dos argumentos constructor, usted puede ir con tu solución, si quieres.


Dicho esto, me gustaría utilizar una fábrica de función, porque de decidir sobre el tipo el significado de los parámetros es muy frágil, creo.La mayoría de la gente esperaría que el resultado siguiente a la igualdad de

PointList p(floor(1.5));
PointList u((int)1.5);

Pero el resultado sería un estado diferente de cosas.

Otros consejos

¿Por qué no usar métodos de fábrica en lugar de constructores? Los métodos de fábrica tienen la ventaja de nombres personalizables.


static PointList createNearestValues(unsigned int maxvals) {}
static PointList createByDistance(float maxdist) {}

Considere usar true typedefs . Es un poco más de esfuerzo por parte de su código de cliente, pero se le garantiza la corrección.

Llame a PointList (10) para el primero y PointList (10f) para el segundo.

Para el segundo, también puede usar 10.0.

Si los constructores n. ° 1 y n. ° 2 están presentes, se llamará al constructor correcto si el valor que inserta es float o int y no se debe realizar ninguna conversión. Tan solo asegúrese de hacer explícitos los tipos de números que usa para llamar (es decir, 1f y 1). Constructor # 3 no parece ser una gran opción, ya que no es realmente necesario y solo confundiría a los usuarios de su código. Si necesita valores predeterminados para cualquier número, puede usar

PointList(int max, float max=VALUE)

y

PointList(float max, int max=VALUE)

Nuevamente: esto parece hacer más daño que el código en términos de legibilidad del código.

Esto requiere una buena lectura en Resolución de sobrecarga .

Definitivamente usaría constructores explicit . En el ejemplo, el entero sin signo no se convierte implícitamente.

class A
{
public:
    explicit A(float f){}
    explicit A(int i){}
};

void test(){
    unsigned int uinteger(0);
    A a1(uinteger);        //Fails, does not allow implicit conversions

    A a2((float)uinteger); //OK, explicit conversion

    float f(0.0);
    A a3(f);               //OK

    int integer(0);
    A a4(integer);         //OK
}

El mensaje de error es bastante fácil de entender:

: error C2668: 'A::A' : ambiguous call to overloaded function
: could be 'A::A(int)'
: or       'A::A(float)'
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top