2012-02-06 18 views
7

Estoy teniendo dificultades para la formación de una cuestión de lo que estoy tratando de preguntar por lo que te voy a dar un ejemplo:operador básico de la sobrecarga de sintaxis en C++

decir que estamos trabajando en un sistema en el que tenemos 3d definió una clase vectorial, Vec3. Sobrecargamos algunos operadores aritméticos para resons obvios. Entre estos, sobrecargamos el operador * para que devuelva el producto escalar de dos vectores. Ahora nuestro código debe ser algo como esto:

class Vec3{ 
private: 
    float x, y, z; 
public: 
    float operator*(const Vec3&) const; //dot product 
. 
. 
. 

Ahora dicen que queremos ser capaces de escalar nuestro vector mediante el operador * con algo, por ejemplo un flotador. Esto podría hacerse al declarar lo siguiente:

Vec3 operator*(const float) const; 
    friend Vec3 operator*(const float, const Vec3&); 

este yeilds dos sobrecargas y Me pregunto si hay una manera de hacerlo con una sola, es decir, decimos declaramos esto en vez de las dos líneas anteriores:

friend Vec3 operator*(const Vec3&, const Vec3&); 

y luego añadir valores por defecto para el ctor vec3 para manejar la conversión de flotador.

Este último ejemplo podría funcionar para:

Vec3 someVec3 = 1.0 * otherVec3; //through friend Vec3 operator*(const float, const Vec3&) 
sin embargo, no

para esto:

Vec3 someVec3 = otherVec3 * 1.0; 

como el compilador no sabría cuál de los dos instrumentos debe utilizar:

friend Vec3 operator*(const float, const Vec3&); //the one we want to use 
or 
    float operator*(const Vec3&) const; //the one for the dot product 

¿Alguna sugerencia?

¡Gracias!

+3

¿Qué pasa con dos sobrecargas? Como usted señala, se crea una ambigüedad bastante desagradable cuando se intenta simplificar en exceso ... –

+2

Lo único que haría de manera diferente, es hacer que ambas versiones de las funciones de amigo escalar se multipliquen en lugar de ser un miembro, de modo que el código tener la misma simetría que la operación misma. –

+0

Sería ineficiente construir un vector solo para pasar un flotador. Esto sería una ineficiencia de tiempo de ejecución, pero una función sobrecargada adicional podría estar integrada. – QuentinUK

Respuesta

5

En este caso, al principio me aconsejaría contra la sobrecarga de operadores, porque ¿cómo son sus usuarios saber si * representa punto o producto cruzado (ambos son razonables significados dependiendo del uso del cliente esperado). De hecho, sugeriría que no admitiría operator* y lo haría con los miembros dot, cross y scale. Entonces no tiene que preocuparse por sobrecargas múltiples y sus usuarios lo tienen claro.

Sin embargo, si desea seguir adelante con los operadores, no hay nada de malo en tener dos sobrecargas. Crear un dummy Vec3 para escalar no solo es semánticamente incorrecto sino que va a agregar una pequeña cantidad de sobrecarga innecesaria.

1

No hay nada malo en un par de sobrecargas, sobre todo si pueden ser fácilmente implementados en términos de uno al otro:

Vec3 operator*(const float scale, const Vec3& vec) 
{ return vec * scale; } 

Es difícil conseguir que sea más fácil que eso!

2

Boost.Operators puede hacer la mayor parte del trabajo de la placa de la caldera para usted. Ej .:

class Vec3 
    : boost::multipliable2<Vec3, float> 
{ 
public: 
    // ... 

    Vec3 operator*=(float); 
    // Vec3 operator*(Vec3, const float&) and 
    // Vec3 operator*(const float&, Vec3) auto-generated 
    // by multipliable. 
};