2009-05-15 17 views
12

¿Qué es implicit_cast? ¿Cuándo debería preferir implicit_cast en lugar de static_cast?¿Cuál es la diferencia entre static_cast y Implicit_cast?

+5

En caso de que pregunte abt boost :: implicit_cast; por favor edite la publicación para decirlo con mayor claridad. – Abhay

+0

@Abhay El concepto de 'implicit_cast' es mucho más antiguo que Boost, varios años más antiguo. – curiousguy

+0

@curiousguy: Las cosas como un "reparto implícito" no existen, ya que un reparto siempre es una solicitud de conversión explícita. Lea la respuesta aceptada para obtener detalles ... – Abhay

Respuesta

18

Copio un comentario que hice al answer this comment en otro lugar.

Puedes realizar el castigo con static_cast. No es así con implicit_cast. static_cast básicamente le permite hacer cualquier conversión implícita, y además el reverso de cualquier conversión implícita (hasta algunos límites, no puede abatir si hay una clase base virtual involucrada). Pero implicit_castsolo aceptan conversiones implícitas. sin entrada reparto, no hay void*->T*, sin U->T si T tiene sólo constructores explícitos para U.

Nota que es importante tener en cuenta la diferencia entre un molde y una conversión. En la siguiente sin reparto está pasando

int a = 3.4; 

Pero sucede una conversión implícita del doble a int. Las cosas como un "reparto implícito" no existen, ya que un reparto siempre es una solicitud de conversión explícita. La construcción de nombre para boost::implicit_cast es una hermosa combinación de "conversión usando conversiones implícitas". Ahora toda la implementación de boost::implicit_cast es esto (explicó here):

template<typename T> struct identity { typedef T type; }; 
template<typename Dst> Dst implicit_cast(typename identity<Dst>::type t) 
{ return t; } 

La idea es utilizar un contexto no deducida para el parámetro t. Eso va a evitar errores como los siguientes:

call_const_version(implicit_cast(this)); // oops, wrong! 

Lo que se desea es escribirlo como esto

call_const_version(implicit_cast<MyClass const*>(this)); // right! 

el compilador no puede deducir de qué tipo es el parámetro de plantilla Dst debe nombrar, porque primero debe saber qué es identity<Dst>, ya que es parte del parámetro utilizado para la deducción. Pero a su vez depende del parámetro Dst (identity podría estar explícitamente especializado para algunos tipos). Ahora, tenemos una dependencia circular, para la cual el Estándar simplemente dice que dicho parámetro es un contexto no deducido, y se debe proporcionar un argumento de plantilla explícito.

1

implicit_cast transforma un tipo en otro, y se puede extender escribiendo funciones de conversión implícitas, para convertir de un tipo a otro.

p. Ej.

int i = 100; 
long l = i; 

y

int i = 100; 
long l = implicit_cast<long>(i); 

son exactamente el mismo código

sin embargo puede proporcionar a sus propias conversiones implícitas para sus propios tipos, por la sobrecarga implicit_cast como la siguiente

template <typename T> 
inline T implicit_cast (typename mpl::identity<T>::type x) 
{ 
    return x; 
} 

Ver aquí boost/implicit_cast.hpp para más

espero que esto ayude

EDITAR

Esta página también habla de implicit_cast New C++

Además, la función principal de static_cast es realizar un no cambio o transformación semántica de un tipo a otro. El tipo cambia pero los valores permanecen idénticos, p.

void *voidPtr = . . . 
int* intPtr = static_cast<int*>(voidPtr); 

que desee ver en este puntero nulo, como si fuera un puntero int, el puntero no cambia, y bajo las sábanas voidPtr tiene exactamente el mismo valor que IntPtr. Un implicit_cast, el tipo cambia pero los valores después de la transformación también pueden ser diferentes.

+1

"_ la función principal de static_cast es realizar una transformación semántica o sin cambios de un tipo a otro. El tipo cambia pero los valores permanecen idénticos_" en este caso ('static_cast '), el valor no cambia; en general, 'static_cast' puede cambiar el tipo y el valor: ejemplo obvio,' static_cast (3.14) ' – curiousguy

1

Las conversiones implícitas, las conversiones explícitas y las static_cast son todas cosas diferentes. sin embargo, si puede convertir implícitamente, puede convertir explícitamente, y si puede convertir explícitamente, puede convertir estáticamente. Lo mismo en la otra dirección no es cierto, sin embargo. Existe una relación perfectamente razonable entre los moldes implícitos y los moldes estáticos . El primero es un subconjunto de este último.

Véase la sección 5.2.9.3 del estándar de C++ para detalles

De lo contrario, una expresión e puede ser convertido explícitamente a un tipo T utilizando un static_cast de la forma static_- fundido (e) si la declaración T t (e); está bien formado, para algunos inventado variable temporal t (8.5).

C++ fomenta el uso de static_casts porque hace la conversión 'visible' en el programa. El uso de los moldes en sí indica alguna regla aplicada por el programador que vale la pena mirar, así que mejor use static_cast.

4

Prefiere implcit_cast si es suficiente en tu caso.implicit_cast es menos poderoso y más seguro que static_cast.

Por ejemplo, la bajada de un puntero base a un puntero derivado es posible con static_cast pero no con implicit_cast. A la inversa, es posible con ambos moldes. Luego, cuando elijas de una base a una clase derivada, usa implicit_cast, porque te mantiene a salvo si confundes ambas clases.

Además, tenga en cuenta que implicit_cast a menudo no es necesario. Al no usar ningún cast, la mayoría de las veces, cuando implicit_cast lo hace, de ahí viene lo "implícito". implicit_cast solo es necesario en circunstancias especiales en las que el tipo de una expresión debe controlarse exactamente, para evitar una sobrecarga, por ejemplo.

+0

Has" derivado "y" base "hacia atrás aquí. Un puntero derivado siempre se puede convertir en una base (pública o accesible), pero la conversión descendente requiere un lanzamiento explícito. –

+0

@ AdamH.Peterson Tienes razón. Acabo de editar la respuesta. –

Cuestiones relacionadas