teorico read programas programar programacion practico para macro libro ingenieros español ejemplos dev descargar def completo como comandos cast c++ implicit-conversion explicit

c++ - read - ¿Se puede usar la palabra clave explícita para evitar la conversión automática de los parámetros del método?



programacion en c++ para ingenieros pdf (7)

Sé que puede usar la palabra clave C ++ ''explicit'' para los constructores de clases para evitar una conversión automática de tipo. ¿Puedes usar este mismo comando para evitar la conversión de parámetros para un método de clase?

Tengo dos miembros de clase, uno que toma un bool como param, y el otro unsigned int. Cuando llamé a la función con un int, el compilador convirtió el param a bool y llamó al método incorrecto. Sé que eventualmente reemplazaré al bool, pero por ahora no quiero romper las otras rutinas a medida que se desarrolla esta nueva rutina.


Algo que podría funcionar para usted es usar plantillas. A continuación, se muestra la función de plantilla foo<>() especializada para bool , unsigned int e int . La función main() muestra cómo se resuelven las llamadas. Tenga en cuenta que las llamadas que usan una constante int que no especifica un sufijo de tipo se resolverán en foo<int>() , por lo que obtendrá un error al llamar a foo( 1) si no se especializa en int . Si este es el caso, los llamantes que usen una constante literal entera tendrán que usar el sufijo "U" para que la llamada se resuelva (este podría ser el comportamiento que desea).

De lo contrario, tendrás que especializarte en int y usar el sufijo "U" o convertirlo a un unsigned int antes de pasarlo a la versión unsigned int (o tal vez hacer una afirmación de que el valor no es negativo, si eso es lo que querer).

#include <stdio.h> template <typename T> void foo( T); template <> void foo<bool>( bool x) { printf( "foo( bool)/n"); } template <> void foo<unsigned int>( unsigned int x) { printf( "foo( unsigned int)/n"); } template <> void foo<int>( int x) { printf( "foo( int)/n"); } int main () { foo( true); foo( false); foo( static_cast<unsigned int>( 0)); foo( 0U); foo( 1U); foo( 2U); foo( 0); foo( 1); foo( 2); }


El compilador dio una advertencia de "llamada ambigua", que será suficiente.

Estaba desarrollando TDD y no me había dado cuenta de que olvidé implementar la llamada correspondiente en el objeto simulado.


No. explicit evita la conversión automática entre clases específicas, independientemente del contexto. Y, por supuesto, no puedes hacerlo para las clases integradas.


También podría escribir una versión int que llame al bool.


bool IS es una int que está limitada a 0 o 1. Ese es el concepto completo de return 0 ;, lógicamente es lo mismo que decir return false; (sin embargo, no use esto en el código).


No, no puede usar explícito, pero puede hacer esto en su lugar:

class ClassThatOnlyTakesBoolsAndUIntsAsArguments { public: void Method(bool arg1); void Method(unsigned int arg1); // Below just an example showing how to do the same thing with more arguments void MethodWithMoreParms(bool arg1, SomeType& arg2); void MethodWithMoreParms(unsigned int arg1, SomeType& arg2); private: template<typename T> void Method(T arg1); // Below just an example showing how to do the same thing with more arguments template<typename T> void MethodWithMoreParms(T arg1, SomeType& arg2); };

Repita este patrón para cada método que toma el bool o unsigned int . No proporcione una implementación para la versión con plantilla del método.

Esto forzará al usuario a llamar siempre explícitamente a la versión bool o unsigned int.

Cualquier intento de llamar a Method con un tipo distinto de bool o unsigned int no compilará porque el miembro es privado, sujeto a las excepciones estándar a las reglas de visibilidad, por supuesto (amigo, llamadas internas, etc.). Si algo que tiene acceso llama al método privado, obtendrá un error de enlazador.


El siguiente es un contenedor muy básico que se puede usar para crear un typedef fuerte:

template <typename V, class D> class StrongType { public: inline explicit StrongType(V const &v) : m_v(v) {} inline operator V () const { return m_v; } private: V m_v; // use V as "inner" type }; class Tag1; typedef StrongType<int, Tag1> Tag1Type; void b1 (Tag1Type); void b2 (int i) { b1 (Tag1Type (i)); b1 (i); // Error }

Una buena característica de este enfoque es que también puede distinguir entre diferentes parámetros con el mismo tipo. Por ejemplo, podría tener lo siguiente:

class WidthTag; typedef StrongType<int, WidthTag> Width; class HeightTag; typedef StrongType<int, HeightTag> Height; void foo (Width width, Height height);

Será claro para los clientes de ''foo'' qué argumento es cuál.