Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Программирование основы языка С++. Учебное пособие
.pdf
собственные литералы (user-defined literals). Для создания собственного
литерала используется синтаксис похожий на перегрузку операций.
4.7 Константы в С++
Константы в С++ аналогичны константам в Си. Для представления константы в Си использовалась только директива препроцессора
#define:
#define MAX 100
В С++ для представления константы рекомендуется использовать
объявление переменной с начальным значением и ключевым словом
const:
const тип ИмяПеременной = НачальноеЗначение;
const int n=10;
Область видимости константы такая же, как у обычной переменной. С помощью ключевого слова const можно объявить указатель на
константу:
const тип *ИмяПеременной;
const int *m; // m – указатель на константу типа int
const int n=3;
m = &n;
Еще одна возможность const состоит в создании постоянного указателя на величину указанного типа:
тип *const ИмяПеременной = Значение;
int i;
int *const ptri=&i;
Использование const имеет несколько преимуществ по сравнению с
#define. При объявлении константы с использованием const явно указы-
вается тип величины. Константа, объявленная с использванием const,
просто согласуется с производными типами, например, объявление
массива:
const int base_vals[5] = { 1000, 2000, 3500, 6000, 10000};
Идентификаторы const подчиняются тем же правилам, что и переменные. Можно создавать константы с различной областью видимости.
51

4.8 Перечислямый тип данных
В С++ можно создавать свои типы данных. Для реализации соб-
ственного типа данных используется перечисляемый тип данных.
Перечисление («перечисляемый тип») – это тип данных, где любое
значение (или еще «перечислитель») определяется как символьная константа. Объявляется перечисление с помощью ключевого слова enum:
//объявляем новый тип данных Месяц
enum Months
{
//здесь перечисляем все возможные значения
//каждый разделитель разделяется запятой(!)
JANUARY,
FEBRUARY,
MARCH,
APRIL,
MAY,
JUNE,
JULY,
AUGUST,
SEPTEMBER,
OCTOBER,
NOVEMBER,
DECEMBER
}; //enum обязательно заканчивается точкой с запятой
Months my_month= JANUARY; //определяем переменную my_month типа
enum
Объявление перечислений не требует выделения памяти, только
когда переменная перечисляемого типа определена, тогда и выделяется
память для этой переменной.
Идентификаторы перечислений начинаются с заглавной буквы, а
имена перечислителей состоят только из заглавных букв. Так как перечислители находятся в одном пространстве имен с перечислением, поэтому одно и то же имя одного перечислителя не может быть использовано в нескольких перечислениях одного и того же пространства имен:
enum Months
{
JANUARY, //данный перечислитель находится в глобальном пространтсве имен
52

FEBRUARY,
MARCH
};
enum Size
{
JANUARY, // ошибка, т.к. уже используется данный перечислитель
BIG,
SMALL
};
Каждому перечислителю автоматически присваивается целочисленное значение в зависимости от его позиции в списке перечисления.
Можно назначать значения самостоятельно, при этом не определенные
перечислители будут иметь значения на 1 больше, чем значения предыдущего. При этом необходимо иметь ввиду, что присваивать одно и
тоже значение разным перечислителям не рекомендуется. По умолчанию, первому перечислителю присваивается целое число 0, а каждому
следующему – на единицу больше, чем предыдущему:
enum Months
{
JANUARY, //=0
FEBRUARY, //=1
MARCH, //=2
APRIL, //=3
MAY, //=4
JUNE, //=5
JULY, //=6
AUGUST, //=7
SEPTEMBER, //=8
OCTOBER, //=9
NOVEMBER, //=10
DECEMBER //=11
};
При использовании перечислителей необходимо иметь ввиду, что
компилятор будет работать с присвоенными значениями, и, следовательно, не позволит осуществлять ввод/вывод перечислителей через
стандартный ввод/вывод:
53

#include <iostream>
enum Months
{
JANUARY, //=0
FEBRUARY, //=1
MARCH, //=2
APRIL, //=3
MAY, //=4
JUNE, //=5
JULY, //=6
AUGUST, //=7
SEPTEMBER, //=8
OCTOBER, //=9
NOVEMBER, //=10
DECEMBER //=11
};
int main()
{
Months my_m, my_m1=JUNE;
std::cin >> my_m; //ошибка
std::cout << my_m1; //выведет 5
return 0;
}
4.9 Преобразование типов
4.9.1 Оператор явного преобразования типа: (). В C++ разрешаются
явные преобразования типов с использованием синтаксиса, аналогичного синтаксису вызова функции:
simple-type-name (expression-list)
Явное преобразование типа в тип int:
int i = int( d );
Явное преобразование типа а тип float:
int i = 7;
float d;
d = float( i );
Явные преобразования типов также можно задавать с помощью
синтаксиса приведения:
54

d = (float)i;
Преобразования отдельных значений в стиле приведения и в стиле функции дают одинаковые результаты. Однако в синтаксисе стиля
функции можно определить несколько аргументов для преобразования.
Внимание! Явные преобразования типов следует использовать с
осторожностью, поскольку они переопределяют встроенную проверку
типов компилятора C++.
4.9.2 Стандартные преобразования. В языке C++ определены преобразования между его основными типами. Также определяются преобразования для указателей, ссылочных типов и типов указателей на члены,
такие преобразования называются стандартными преобразованиями:
восходящие приведения целочисленных типов;
•
преобразования целочисленных типов;
•
преобразования типов с плавающей запятой;
•
преобразования типов с плавающей запятой и целочисленных типов;
•
арифметические преобразования;
•
преобразования указателей;
•
преобразования ссылок;
•
преобразования указателей на члены.
•
Восходящие приведения целочисленных типов. Объекты целочислен-
ного типа можно преобразовать в другой более широкий целочисленный
тип, то есть тип, который может представлять больший набор значений.
Этот расширяющий тип преобразования называется целочисленным по-
вышением. С помощью целочисленного повышения можно использовать
следующие типы в выражении, где можно использовать другой целочисленный тип:
объекты, литералы и константы типа char и short int
•
типы перечисления.
•
битовые поля int
•
перечислители.
•
Обычно при повышениях с сохранением значения и повышениях с
сохранением наличия знака выдаются одинаковые результаты. Однако
они могут дать разные результаты, если объект повышенного уровня
выглядит следующим образом:
Операнд /, %, /=, %=, <, <=, > или >= – эти операторы зависят от
•
знака для определения результата. При применении к этим операндам
предложения с сохранением и обслуживанием, сохраняя при этом
подписи, получают разные результаты.
55

Левый операнд >> или >>= – эти операторы обрабатывают ко-
•
личества со знаком и без знака по-разному в операции сдвига. Для
количества со знаком операция сдвига вправо распространяет бит
знака на освобожденные позиции битов, а освобожденные разряды
заполняются нулем в неподписанных количествах.
Аргумент для перегруженной функции или операнд перегруженного
•
оператора, который зависит от подписи типа операнда для соответствующего аргумента. Дополнительные сведения об определении
перегруженных операторов см. в разделе перегруженные операторы.
Преобразования целочисленных типов
Целочисленные преобразования – это преобразования между целочисленными типами. Целочисленные типы – char, Short (или short int),
int, Longи long long. Эти типы могут быть дополнены со знаком или без
знака.
Преобразование чисел со знаком в числа без знака. Объекты целочисленных типов со знаком можно преобразовывать в соответствующие
типы без знака. При возникновении этих преобразований фактический
битовый шаблон не изменяется:
#include <iostream>
using namespace std;
int main()
{
// определяется и задается короткое значение со знаком, i, которое
инициализируется с
// отрицательным числом
short i = –3;
unsigned short u;
//(u = i) выражения приводит к тому, что i преобразуются в неподписанный короткий промежуток перед присваиванием u
cout << (u = i) << "\n";
}
// Output: 65533
Преобразование чисел без знака в числа со знаком. Объекты целочисленных типов без знака можно преобразовывать в соответствующие
типы со знаком. Однако если значение без знака находится за пределами представимого диапазона типа со знаком, результат не будет иметь
правильное значение, как показано в следующем примере:
#include <iostream>
56

using namespace std;
int main()
{
short i;
unsigned short u = 65533;
// u является неподписанным коротким целым объектом, который
необходимо
// преобразовать в число со знаком, чтобы вычислить выражение (i = u).
cout << (i = u) << "\n";
}
// поскольку его значение не может быть правильно представлено ко-
ротким знаком,
// данные будут неправильно интерпретированы
//Output: –3
Преобразование чисел с плавающей запятой. Объект типа с плавающей запятой можно безопасно преобразовать в более точный тип с
плавающей запятой, то есть без потери значимости. Например, при преобразовании с плавающей запятой в Double или из двойного в длинное
двойное значение может быть безизменным. Объект плавающего типа
также можно преобразовать в менее точный тип, если он находится в
диапазоне, представленном этим типом. Если исходное значение не
может быть представлено точно, его можно преобразовать в следующее
большее или следующее более низкое значение. Если такого значения
не существует, результат будет неопределенным. Рассмотрим следующий пример:
std::cout << (float)1E300 << std::endl;
Максимальное значение, которое может быть представлено типом
float , – это 3.402823466E38 – намного меньшее число, чем 1E300. Таким
образом, число преобразуется в бесконечное значение, а результатом
является "INF".
Преобразования между целочисленным типом и типом с плавающей
запятой. Определенные выражения могут вызывать преобразование
объектов плавающего типа в целочисленные типы, и наоборот. Если
объект целочисленного типа преобразуется в тип с плавающей запятой,
а исходное значение не может быть представлено точно, результатом
является либо следующее выше, либо следующее меньшее представимое
значение. При преобразовании объекта с плавающего типа в целочисленный тип дробная часть усекаетсяили округляется в сторону нуля.
57

Число, например 1.3, преобразуется в 1, а (-1.3) преобразуется в (-1).
Если усеченное значение выше наибольшего допустимого значения
или меньше наименьшего представимого значения, результат будет
неопределенным.
Арифметические преобразования. Многие бинарные операторы приводят к преобразованию операндов и выдают результаты одинаковым
образом. Арифметические преобразования операндов, которые имеют
различные собственные типы, выполняются, как показано на рисунке 4.1. Типы typedef ведут себя в соответствии со своими базовыми
собственными типами.
Рисунок 4.1
Преобразования указателей. Указатели можно преобразовывать в
ходе присваивания, инициализации, сравнения и выполнения других
выражений.
Указатель на классы. Указатель на класс можно преобразовать в указатель на базовый класс в двух случаях:
Во-первых, когда указанный базовый класс доступен и преобразование однозначно. Дополнительные сведения об неоднозначных ссылках
58

на базовые классы см. в разделе несколько базовых классов. Доступность
базового класса зависит от используемого типа наследования (рис. 4.2).
Рисунок 4.2 – допустимость преобразования
Во-вторых, указатель на класс можно преобразовать в указатель
на базовый класс при использовании явного преобразования типов.
Результатом такого преобразования является указатель на подобъект,
часть объекта, полностью описываемого базовым классом.
Указатель на функцию. Указатель на функцию можно преобразовать
в тип void *, если тип void * достаточно большой для хранения этого
указателя.
Указатель на void. Указатели на тип void можно преобразовать в указатели на любой другой тип, но только с явно приведенным типом.
Указатель на любой тип можно преобразовать неявно в указатель на
тип void. Указатель на неполный объект типа может быть преобразован
в указатель на void (неявно) и обратно (явно). Результат такого преобразования равен значению исходного указателя. Объект считается неполным, если он объявлен, но недостаточно информации для определения
его размера или базового класса. Указатель на любой объект, который
не является константой или volatile, может быть неявно преобразован
в указатель типа void *.
59

4.10 Контрольные вопросы
1. Язык программирования C++ разработал:
a. Никлаус Вирт
b. Кен Томпсон
c. Дональд Кнут
d. Бьерн Страуструп
2. Простые типы данных в С++:
a. целые – int, вещественные – float или double, символьные – string
b. целые – int, вещественные – float или real, символьные – char
c. целые – int, вещественные – float или double, символьные – char
d. целые – bool, вещественные – float или double, символьные –
string
3. Какой из перечисленных типов данных не является типом данных
в С++?
a. float
b. int
c. real
d. double
4. Какой оператор не допускает перехода от одного константного
выражения к другому?
a. end;
b. Stop;
c. точка с запятой
d. break;
1. Какие служебные символы используются для обозначения начала
и конца блока кода?
a. < >
b. begin end
c. ( )
d. { }
6. Укажите правильное определение функции main в соответствии
со спецификацией стандарта ANSI:
a. void main()
b. int main(void)
c. void main(void)
d. int main()
7. Выберите правильный вариант объявления константной перемен-
ной в С++, где type - тип данных в С++ variable - имя переменной value -
60
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
