Чтение онлайн

ЖАНРЫ

Программирование. Принципы и практика использования C++ Исправленное издание
Шрифт:

A.5.7. Операторы приведения

Существуют четыре оператора приведения к типу.

Динамическое приведение обычно используется для навигации по иерархии классов, если указатель

p
— указатель на базовый класс, а класс
D
— производный от базового класса. Если операнд
v
не относится к типу
D*
, то эта операция возвращает число
0
. Если необходимо, чтобы
операция
dynamic_cast
в случае неудачи не возвращала
0
, а генерировала исключение
bad_cast
, то ее следует применять к ссылкам, а не к указателям. Динамическое приведение — единственное приведение, опирающееся на проверку типов во время выполнения программы.

Статическое приведение используется для “разумных преобразований,” т.е. если операнд v может быть результатом неявного преобразования типа

T
(см. раздел 17.8).

Оператор

reinterpret_cast
используется для реинтерпретации комбинации битов. Его переносимость не гарантируется. Фактически лучше считать, что он является вообще не переносимым. Типичным примером реинтерпретации является преобразование целого числа в указатель, чтобы получить машинный адрес в программе (см. разделы 17.8 и 25.4.1).

Приведения в стиле языка С и функциональные приведения могут выполнить любое преобразование типа, которое можно осуществить с помощью оператора

static_cast
или
reinterpret_cast
в сочетании с оператором
const_cast
.

Приведений лучше избегать. Во многих ситуациях их использование свидетельствует о плохом стиле программирования. Исключения из этого правила представлены в разделах 17.8 и 25.4.1. Приведение в стиле языка С и функциональные приведения имеют ужасное свойство: они позволяют вам не вникать в то, что именно они делают (см. раздел 27.3.4). Если вы не можете избежать явного преобразования типа, лучше используйте именованные приведения.

A.6. Инструкции

Грамматическое определение инструкций языка C++ приведено ниже (opt означает “необязательный”).

инструкция:

объявление

{ список_инструкции opt }

try
{ список_инструкции opt } список_обработчиков

выражение opt;

инструкция_выбора

инструкция_итерации

инструкция_с_метками

управляющая_инструкция

инструкция_выбора:

if
(условие) инструкция

if
(условие) инструкция
else
инструкция

switch
(условие) инструкция

инструкция_итерации:

while
(условие) инструкция

do
инструкция
while
(выражение);

for
(инструкция_инициализации_for
условие opt; выражение opt) инструкция

инструкция_с_метками:

case
константное_выражение: инструкция

default:
инструкция

identifier:
инструкция

управляющая_инструкция:

break;

continue;

return
выражение opt;

goto
идентификатор;

список_инструкции:

инструкция список_инструкции opt

условие:

выражение

спецификатор_типа объявляемый_объект = выражение

инструкция_инициализации_for:

выражение opt;

спецификатор_типа объявляемый_объект = выражение;

список_обработчиков:

catch
(объявление_исключения) { список_инструкции opt }

список_обработчиков список_обработчиков opt

Обратите внимание на то, что объявление — это инструкция, а присваивание и вызов функции являются выражениями. К этому определению следует добавить следующий список.

• Итерация (

for
и
while
); см. раздел 4.4.2.

• Ветвление (

if
,
switch
,
case
и
break
); см. раздел 4.4.1. Инструкция
break
прекращает выполнение ближайшей вложенной инструкции
switch
,
while
,
do
или
for
. Иначе говоря, следующей будет выполнена инструкция, следующая за последней в теле одной из перечисленных выше инструкций.

• Выражения; см. разделы A.5 и 4.3.

• Объявления; см. разделы A.6 и 8.2.

• Исключения (

try
и
catch
); см. разделы 5.6 и 19.4.

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

int* f(int p[],int n)

{

if (p==0) throw Bad_p(n);

vector<int> v;

int x;

while (cin>>x) {

Поделиться с друзьями: