Как общее правило, это очень часто считают плохой практикой для использования const_cast<>()
в коде C++, поскольку это показывает (большую часть времени) дефект в дизайне.
В то время как я полностью соглашаюсь с этим, я однако задаюсь вопросом, что является случаями, использовали const_cast<>()
в порядке и единственное решение.
Могли Вы парни, дайте мне некоторые примеры, которые Вы знаете/Вы встреченный?
Большое спасибо.
const_cast
также используется для удаления модификаторов volatile
, как показано на практике в этой (спорной) статье:
Да, конечно, когда ваш вызывающий код, который вы не можете изменить, не является правильным с константой. Следует отметить, что вы должны использовать его только с вызовами функций, которые, как вы точно знаете, не изменят ваши данные!
Я согласен с вашим утверждением, что его нормальное использование связано с тем, что вам нужно скрыть «недостаток дизайна».
IME - один из типичных сценариев использования - когда вы пытаетесь связать C ++ с существующим кодом C. Большая часть существующего кода C принимает строки C как char *
, даже если строка не модифицируется, тогда как они обычно представлены как что-то, что преобразуется в const char *
в C ++. Это несоответствие импеданса между двумя языками, которое вы обычно решаете с помощью const_cast. Конечно, вам лучше быть очень уверенным, что код, с которым вы взаимодействуете, не содержит никаких хороших идей об изменении передаваемых данных.
Я бы сказал, что это запах кода во вновь написанном коде, но для взаимодействия со старым кодом C и C ++ это неизбежное зло. Тем не менее, я был бы крайне осторожен с кодом, который требует const_cast
для любых объектов, не относящихся к POD, поскольку это обычно проблема, которую следует решать на уровне дизайна, а не на уровне кода.
он в значительной степени предназначен для использования только с устаревшими API, которые не являются корректными константами, то есть с функцией, которую вы не можете изменить, которая имеет неконстантный интерфейс, но фактически ничего не изменяет в интерфейсе
Как говорили другие, его основная цель - удалить const
из объектов, чтобы перейти к неконстантным правильным функциям, которые, как вы знаете, не изменят аргумент.
Есть уловка (от Мейерса?), Позволяющая избежать дублирования кода, и она выглядит так:
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());
}
};
Одно вполне законное использование этого - когда у вас есть и константный, и неконстантный api (для константных и неконстантных объектов соответственно), как в
class Bar {
const SomeType& foo() const;
SomeType& foo();
}
Тогда, поскольку мы не хотим дублировать код в обеих функциях, мы часто use
class Bar {
SomeType& foo() {
//Actual implementation
}
const SomeType& foo() const {
return const_cast<Bar*>(this)->foo();
}
};
Это, конечно, предполагает, что foo не делает что-то, что нарушает семантику констант.