Вход/Регистрация
Программирование. Принципы и практика использования C++ Исправленное издание
вернуться

Страуструп Бьерн

Шрифт:

Естественно, мы не хотели бы совсем отказываться от защиты, представляемой системой типов, но иногда у нас нет логичной альтернативы (например, когда мы должны обеспечить работу с программой, написанной на другой языке программирования, в котором ничего не известно о системе типов языка С++). Кроме того, существует множество ситуаций, в которых необходимо использовать старые программы, разработанные без учета системы безопасности статических типов.

В таких случаях нам нужны две вещи.

• Тип указателя, ссылающегося на память без учета информации о том, какие объекты в нем размещены.

• Операция, сообщающая компилятору, какой тип данных подразумевается (без проверки) при ссылке на ячейку памяти с помощью такого указателя.

Тип
void*
означает “указатель на ячейку памяти, тип которой компилятору неизвестен”. Он используется тогда, когда необходимо передать адрес из одной части программы в другую, причем каждая из них ничего не знает о типе объекта, с которым работает другая часть. Примерами являются адреса, служащие аргументами функций обратного вызова (см. раздел 16.3.1), а также распределители памяти самого нижнего уровня (такие как реализация оператора
new
).

Объектов типа

void
не существует, но, как мы видели, ключевое слово
void
означает “функция ничего не возвращает”.

void v; // ошибка: объектов типа void не существует

void f; // функция f ничего не возвращает;

// это не значит, что функция f возвращает объект

// типа void

Указателю типа

void*
можно присвоить указатель на любой объект. Рассмотрим пример.

void* pv1 = new int; // OK: int* превращается в void*

void* pv2 = new double[10]; // OK: double* превращается в void*

Поскольку компилятор ничего не знает о том, на что ссылается указатель типа

void*
, мы должны сообщить ему об этом.

void f(void* pv)

{

void* pv2 = pv; // правильно (тип void* для этого

// и предназначен)

double* pd = pv; // ошибка: невозможно привести тип void*

// к double*

*pv = 7; // ошибка: невозможно разыменовать void*

// (тип объекта, на который ссылается указатель,

// неизвестен)

pv[2] = 9; // ошибка: void* нельзя индексировать

int* pi = static_cast<int*>(pv); // OK: явное приведение

// ...

}

Оператор
static_cast
позволяет явно преобразовать указатели типов в родственный тип, например
void*
в
double*
(раздел A.5.7). Имя
static_cast
— это сознательно выбранное отвратительное имя для отвратительного (и опасного) оператора, который следует использовать только в случае крайней необходимости. Его редко можно встретить в программах (если он вообще где-то используется). Операции, такие как
static_cast
, называют явным преобразованием типа (explicit type conversion), или просто приведением (cast), потому что в языке C++ предусмотрены два оператора приведения типов, которые потенциально еще хуже оператора
static_cast
.

• Оператор

reinterpret_cast
может преобразовать тип в совершенно другой, никак не связанный с ним тип, например
int
в
double*
.

• Оператор

const_cast
позволяет отбросить квалификатор
const
.

Рассмотрим пример.

Register* in = reinterpret_cast<Register*>(0xff);

void f(const Buffer* p)

{

Buffer* b = const_cast<Buffer*>(p);

// ...

}

Первый пример — классическая ситуация, в которой необходимо применить оператор

reinterpret_cast
. Мы сообщаем компилятору, что определенная часть памяти (участок, начинающийся с ячейки
0xFF
) рассматривается как объект класса
Register
(возможно, со специальной семантикой). Такой код необходим, например, при разработке драйверов устройств.

Во втором примере оператор

const_cast
аннулирует квалификатор
const
в объявлении
const Buffer*
указателя
p
. Разумеется, мы понимали, что делали.

  • Читать дальше
  • 1
  • ...
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: