c++ - static_cast - static cast
Corregir los usos de const_cast<> (7)
Como regla general, a menudo se considera una mala práctica usar const_cast<>()
en código C ++ ya que revela (la mayoría de las veces) un defecto en el diseño.
Aunque estoy totalmente de acuerdo con esto, me pregunto cuáles son los casos en los que se usa const_cast<>()
y la única solución .
¿Podrían darme algunos ejemplos que saben / se encontraron?
Muchas gracias.
Como otros han dicho, su propósito principal es eliminar const
de los objetos para pasar a funciones no conformes que usted sabe que no modificarán el argumento.
Hay un truco (¿por Meyers?) Para evitar la duplicación de código, y dice así:
struct foo
{
const return_type& get(void) const
{
// fancy pants code that you definitely
// don''t want to repeat
return theValue; // and got it
}
return_type& get(void)
{
// well-defined: Add const to *this,
// call the const version, then
// const-cast to remove const (because
// *this is non-const, this is ok)
return const_cast<return_type&>(static_cast<const foo&>(*this).get());
}
};
Estoy de acuerdo con su declaración de que su uso normal se debe a que necesita ocultar un "defecto de diseño".
IME uno de los escenarios de uso típicos es cuando intentas la interfaz de C ++ con el código C existente. Una gran cantidad de código C existente toma C strings como char *
incluso cuando la cadena no se modifica, mientras que generalmente se representan como algo que se convierte en un const char *
en C ++. Esa es una discrepancia de impedancia entre los dos lenguajes que normalmente resolverías usando un const_cast. Por supuesto, será mejor que estés seguro de que el código con el que interactúas no tiene ninguna idea bonita sobre la modificación de los datos que se transmiten.
Yo diría que es un código que huele a código recién escrito, pero para interactuar con código C y C ++ anterior, es un mal necesario. Dicho esto, sería extremadamente cauteloso con el código que requiere const_cast
para cualquier objeto que no sea POD, ya que normalmente es un problema que debería resolverse en el nivel de diseño y no en el nivel de código.
Sí, por supuesto, cuando su código de llamada no puede modificarse y no es const correcto. ¡Debe tenerse en cuenta que solo debe usarlo con llamadas a funciones que, con certeza, no modificarán sus datos!
Un uso legítimo (en mi opinión) es con std::set
iterators. Siempre están const
, para evitar cambiar la clave utilizada en el conjunto. Cambiar la clave rompería la estructura interna del conjunto y provocaría un comportamiento indefinido.
Sin embargo, mientras la clave no cambie, es seguro cambiar otros datos en el objeto.
Digamos que tienes un std::set
así:
std::set<MyObject> some_set;
Y una clase como esta:
class MyObject {
public:
MyObject(const std::string &key)
: key_(key) {}
bool operator<(const MyObject &other) const {
return key_ < other.key_;
}
private:
// ...
// <some other data>
// ...
const std::string key_;
};
En el ejemplo anterior, la clave ya está const , por lo que incluso si modifica el objeto, no puede romper la estructura interna del conjunto.
Normalmente, solo puede obtener una referencia const
de un iterador de conjunto:
const MyObject &object = *some_set_iterator;
Pero como la clave es const
, es seguro const_cast
el iterador desreferenciado:
MyObject &object = const_cast<MyObject &>(*some_set_iterator);
Un uso muy legítimo de esto es cuando tienes tanto una const como una const api (para objetos const y non const respectivamente) como en
class Bar {
const SomeType& foo() const;
SomeType& foo();
}
Entonces, dado que no queremos duplicar el código en ambas funciones, a menudo usamos
class Bar {
SomeType& foo() {
//Actual implementation
}
const SomeType& foo() const {
return const_cast<Bar*>(this)->foo();
}
};
Esto, por supuesto, supone que foo no hace algo que viole la semántica const.
está diseñado para ser utilizado solo con API heredadas que no son const correctas, es decir, con una función que no se puede cambiar que tiene interfaz no const pero que en realidad no muta nada en la interfaz
const_cast
también se usa para eliminar modificadores volatile
, como se pone en práctica en este artículo (polémico):