static_cast
Операция static_cast
в языке C++ осуществляет явное допустимое приведение типа данных[1].
Синтаксис: static_cast < type_to > ( object_from )
Код скомпилируется, если есть способ преобразования из object_from
в type_to
.
Пример
int nShots = 10, nHits = 8;
auto hitRate = static_cast<float>(nHits) / nShots;
Возможные преобразования типов
static_cast
создан для выполнения всех видов преобразований, разрешённых компилятором[2]. Все преобразования работают, только если есть совместимость по const
и volatile
.
1. Любое из преобразований типа, которые Си++ производит неявно (например, массива в указатель, одного числового типа в другой, void*
-указателя в типизированный, неявный вызов конструктора). Явное написание static_cast
может потребоваться, например:
- в шаблоне;
- для выбора, какую версию функции или операции использовать:
auto hitRate = static_cast<float>(nHits) / nShots;
- чтобы подавить предупреждение компилятора «Возможна потеря точности»:
double a = 1.0; auto b = static_cast<float>(a);
- чтобы согласовать типы в трёхместной условной операции:
Base& x = use1 ? static_cast<Base&>(obj1) : static_cast<Base&>(obj2);
.
2. Если соответствующее преобразование отмечено ключевым словом explicit
.
3. Преобразование из/в тип enum class
.
enum class TriBool { FAL, TRU, UNDEF, NN };
enum { TriBool_N = static_cast<int>(TriBool::NN) };
const char* triBoolNames[TriBool_N] = { "false", "true", "undef" };
auto x = TriBool::TRU;
std::cout << triBoolNames[static_cast<int>(x)] << std::endl;
4. Для явного указания, какую из перегруженных функций брать.
std::transform(s.begin(), s.end(), s.begin(), static_cast<int(*)(int)>(std::toupper));
5. Для преобразования указателей вниз по иерархии типов без проверки типа. В отличие от преобразования в стиле Си и reinterpret_cast
, преобразование в неродственный класс невозможно.
void TSomeForm::someButtonClick(TObject* sender)
{
// Событие C++ Builder
// Мы знаем, что это TButton, ведь мы сами устанавливали событие
// в редакторе форм или конструкторе
TButton* bt = static_cast<TButton*>(sender);
bt->Caption = L"Clicked!";
}
Возможные логические ошибки
Возможные ошибки зависят от того, какое преобразование проводится. Возможны переполнения, выход за диапазон и даже (для преобразования указателей) порча памяти.
Например, при преобразовании int → enum class
переменная может заполучить недопустимое значение и программа не будет готова к этому.
Примечания
- Programming: principles and practice using C++ (англ.). — Соединённые Штаты Америки: Addison-Wesley, 2008. — P. 594. — ISBN 0321543726.
- Thinking in C++ (неопр.). — Соединённые Штаты Америки: Alan Apt, 2000. — С. 857. — ISBN 0-13-979809-9.