tuto try operator dev const_cast cast c++ casting

c++ - try - ¿Cómo puedo prevenir un lanzamiento implícito double-> int?



int to string c++ (4)

Pregunta como arriba, más detalles abajo:

Tengo una clase de Money para tratar ... bueno, adivinaste qué. Soy muy estricto respecto a no permitir que Money y el double interactúen (*), por lo que el siguiente código no es posible:

Money m1( 4.50 ); double d = 1.5; Money m2 = m1 * d; // <-- compiler error

Ahora estoy pensando en permitir la multiplicación de Money con int , ya que en "tienes 6 pedazos de pastel por $ 4.50 cada uno (así que ve y encuentra un pastel más barato en algún lugar)".

class Money { Money(); Money( const Money & other ); explicit Money( double d ); ... Money & operator*=( int i ); ... } inline const Money operator*( const Money & m, int i ) { return Money( m ) *= i; } inline const Money operator*( int i, const Money & m ) { return Money( m ) *= i; }

Eso funciona bien, pero ... desafortunadamente, C ++ hace conversiones implícitas de double a int , así que de repente mi primer fragmento de código se compilará. No quiero eso ¿Hay alguna manera de evitar lanzamientos implícitos en esta situación?

¡Gracias! -- Robin

(*) Motivo: Tengo un montón de códigos heredados que manejan todo lo relacionado con Money con el double , y no quiero que esos tipos se confundan hasta que todo funcione con Money .

Edición: Constructores agregados para el dinero.

Edit: Gracias a todos por sus respuestas. Casi todos fueron geniales y serviciales. El comentario de R. Martinho Fernandes "se puede hacer en inline const Money operator*( const Money & m, double d ) = delete; " fue la respuesta (tan pronto como cambio a un compilador compatible con C ++ 11). Kerrek SB ofreció una buena alternativa de no C ++ 11, pero lo que terminé usando fue el enfoque de "sobrecarga long " de Nicola Musatti. Es por eso que estoy marcando su respuesta como "la respuesta" (también porque todas las ideas útiles surgieron como comentarios a su respuesta). ¡Gracias otra véz!


¿Qué tal una plantilla más la verificación de rasgos de tiempo de compilación?

#include <type_traits> // ... template <typename T> Money & operator*=(const T & n) { static_assert(std::is_integral<T>::value, "Error: can only multiply money by integral amounts!"); // ... }


Podría agregar una declaración para una sobrecarga privada de su operador de asignación aumentada:

private: Money & operator*=( double i );


Puedo pensar en dos maneras de proporcionar esto:

  • usando plantillas y cheques de "concepto"
  • o usando sobrecargas "prohibidas"

Usar sobrecargas es la solución C ++ 11. ¡C ++ 11 introduce la palabra clave delete especialmente para su caso!

Money& operator*=(int i); Money& operator*=(float f) = delete; Money operator*(Money m, int i) { return m*i; } Money operator*(Money m, float f) = delete; Money operator*(int i, Money m) { return m*i; } Money operator*(float f, Money m) = delete;

La forma antigua de hacerlo (C ++ 03) era doble:

  • En la clase, declare el método private
  • no defina el método y espere a que el vinculador se queje

El segundo es una salvaguardia en el caso del método de clase, y la única forma en el caso del método libre. Es triste que solo se detecte en el momento del enlace ... y la palabra clave delete es mucho más agradable;)

Usar plantilla es otra solución. Puede usar std::enable_if o static_assert : uno eliminará la función del conjunto de sobrecarga (SFINAE) mientras que el otro hará que la creación de instancias falle (error del compilador).

Ejemplo:

// For enable_if template <typename T> std::enable_if<std::is_integral<T>::value, Money&> operator*=(T t); template <typename T> std::enable_if<std::is_integral<T>::value, Money> operator*(Money m, T t); template <typename T> std::enable_if<std::is_integral<T>::value, Money> operator*(T t, Money m);

Los ejemplos de static_assert son más naturales (en realidad, como un static_assert regular).

Prefiero recomendar la sobrecarga + delete si la tiene. Si no lo hace, entonces una alternativa al caso de la plantilla es probablemente la mejor solución, ya que es más fácil corregir los errores del compilador que los del enlazador.


puede crear un tipo de titular de número pequeño que tenga todas las propiedades que desea, y luego usarlo para interactuar con otros tipos, como Money .