Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Алгоритмизация и программирование на языке С++. Ч.1. Учебник

.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
2 Мб
Скачать
Приложение 2 Типизация языков программирования
201
ких выражений. Выражения содержат операнды разных ти­пов, однако тип этой переменной всегда остается целым. Для вывода типа переменной использован оператор
name
свойство
[41]. Для ее применения надо в программе доба-
typeid(a)
и его
вить описание [42]:
#include <typeinfo>
Результат выполнения приведенного фрагмента представ­лен на рис. П2.2. Как видно, первые три строки заканчива­ются символом
, что означает тип целый
int
. Значение вы-
i
ражение в четвертой строке равняется 51, потому что целое значение равно 50 (код символа 2).
Рис. П2.2. Тип выражения с переменной целого типа
Приведем еще пример, в котором идентифицируются типы переменных.
int f() { cout << " f"; return 0; }
int main(){
char c1; cout << " char " << typeid(c1).name() << endl; bool b2; cout << " bool " << typeid(b2).name() << endl;
202
АЛГОРИТМИЗАЦИЯ ИПРОГРАММИРОВАНИЕ НАЯЗЫКЕ С++
unsigned long ul3; cout << " unsigned long " << typeid(ul3).name() << endl;
oat f4; cout << " oat " << typeid(f4).name() << endl; double d5; cout << " double " << typeid(d5).name() << endl;
int ar[5];
cout << " Array " << typeid(ar).name() << endl;
cout << " f " << typeid(f).name() << endl; }
Результат приведен на рис. П2.3.
Рис. П2.3. Тип выражения с объектами разных типов
Как видно, определить тип можно не только у простых пе­ременных, а также у массива и функции.
Заметим, что переопределить тип переменной в С++ нель­зя. Если после операторов
int a;
cout << " a=1 " << a << " " << typeid(a).name() << endl;
написать
oat а;
то будет выводиться сообщение об ошибке:
Приложение 2 Типизация языков программирования
203
[Error] conicting declaration 'oat a' [Note] previous declaration as 'int a'
Начиная с С++11, оператор
auto
, уже упомянутый ранее, приобретает новые возможности. При его использовании тип переменной определяется на этапе компиляции на основе при­сваиваемого значения (инициализации).
auto
Попытка применить дважды оператор
к одной пере-
менной
auto a = 1; cout << " a=1 " << a << " " << typeid(a).name() << endl;
auto a = 1.0; a = a + 1.0; cout << " a=1+1 " << a << " " << typeid(a).name() << endl;
так же вызовет ошибки трансляции:
[Error] conicting declaration 'auto a' [Note] previous declaration as 'int a'
Рассмотрим, как вычисляются значения выражений раз­ного типа в С++. В приведенном фрагменте выводятся значе­ния выражений типа
bool, char, int
и
oat
.
#include <iostream> using namespace std;
int main(int argc, char** argv) {
bool tf= 2>1;
std::cout << " 1: " << tf << ios::boolalpha << " " << tf <<"\n";
tf= 2<=1;
std::cout << " 2: " << tf << "\n";
tf = 1;
std::cout << " 3: " << tf << "\n";
char c1='1'; int i2=2; oat f3 = 2.0;
204
АЛГОРИТМИЗАЦИЯ ИПРОГРАММИРОВАНИЕ НАЯЗЫКЕ С++
cout << "\n" << "+ " << endl; cout << " char+int " << (c1+i2) << endl;
cout << " char+oat " << (c1+f3) << endl; cout << " char+int+oat " << (c1+i2+f3) << endl;
cout << " (int)char " << ((int(c1))) << endl;
cout << "\n" << "2+ " << endl; cout << " char+int " << (i2+c1) << endl;
cout << " char+oat " << (f3+c1) << endl; cout << " char+int+oat " << (f3+i2+c1) << endl;
cout << " (int)char " << ((int(c1))) << endl;
cout << "\n" << "* " << endl; cout << " char*int " << (c1*i2) << endl;
cout << " char*oat " << (c1*f3) << endl; cout << " char*int*oat " << (c1*i2*f3) << endl;
cout << "\n" << "/ " << endl; cout << " char/int " << (c1/i2) << endl;
cout << " char/oat " << (c1/f3) << endl; cout << " char/int/oat " << (c1/i2/f3) << endl;
return 0; }
Результат выполнения приведен на рис. П2.4.
Как было сказано ранее, динамическая типизация опре­деляет возможность изменения типа переменных. Примером языка такого класса является, например, Python. Рассмотрим пример [43]:
a = 5
print(a)
a=3.14
print(a)
a='yes'
print(a)
Результат выполнения приведен на рис. П2.5.
Приложение 2 Типизация языков программирования
Рис. П2.4. Разные типы выражений в С++
205
Рис. П2.5. Изменение типа переменной в программе
на Python
В этом примере переменной с именем а присваивается три значения разных типов: целое, вещественное и символьное.
type()
Узнать их тип можно с помощью функции
. Например,
такая пара операторов
206
АЛГОРИТМИЗАЦИЯ ИПРОГРАММИРОВАНИЕ НАЯЗЫКЕ С++
a=1/2 print(' a=1/2 ', type(a) )
выведет следующий результат (рис. П2.6).
Рис. П2.6. Использование функции
type()
Теперь поговорим о том, как вычисляются значения вы­ражений, содержащие операнды разных типов. В языке про­граммирования Python использование операндов разных типов в одном выражении работает по-разному. Например, в при­веденном далее примере операция сложения применяется для операндов двух типов – символьного и целого:
>>> a="2" >>> a=a+4
Выполнение такого фрагмента невозможно. Выводится сообщение об ошибке:
Traceback (most recent call last): File "<pyshell#1>", line 1, in <module>
a=a+4
TypeError: can only concatenate str (not "int") to str
Изменим порядок использования переменных. Все равно выводится сообщение об ошибке:
>>> a=2 >>> a=a+"4"
Traceback (most recent call last): File "<pyshell#1>", line 1, in <module>
a=a+"4"
TypeError: unsupported operand type(s) for +: 'int' and 'str'
Приложение 2 Типизация языков программирования
207
А вот использовать в выражении операнды целого и логи­ческого типа возможно. При этом логическое значение True интерпретируется как целочисленная 1, а False – как 0.
>>> v=1
>>> v 1
>>> v=v+True
>>> v 2
>>>v=v+False
>>>v 2
Посмотрим, как вычисляются выражения, содержащие операнды разных типов в JavaScript. Для типизированных объектов может быть определена слабая версия. Если при сильной типизации в выражения могут встречаться операн­ды только одного типа, то при слабой можно сочетать объекты с разными свойствами. Но работает это по-разному. Напри­мер, такой фрагмент [44] на языке JavaScript (использован онлайн компилятор по адресу – https://www.programiz.com/ javascript/online-compiler/)
5+'6' //'56'
4*'3' // 12 2+true; // 3 False-4;// –4
приведет к результатам, приведенным как комментарии в каждой строке.
Видно, что отдельные элементы выражения обрабатыва­ются как символьные или целочисленные. Это зависит от опе­рации. Для сложения – это символьные данные, а для умно­жения – числовые. А логические значения интерпретируются как 0, если это False, и как 1 если это True.
Переменная в JavaScript может содержать данные любо­го типа. В один момент там может быть, например, строка, а в другой – число:
// Не будет ошибкой
208
АЛГОРИТМИЗАЦИЯ ИПРОГРАММИРОВАНИЕ НАЯЗЫКЕ С++
let message = "hello"; message = 123456;
В заключение приведем фрагмент с упомянутого ранее ре­сурса [https://habr.com/ru/post/161205/]. Здесь приведены данные о языках программирования и какой тип типизации они поддерживают.
Замечание. В таблице изменен порядок строк.
C Статическая Слабая Явная C++ Статическая Слабая Явная C# Статическая Сильная Явная Objective-C Статическая Слабая Явная Python Динамическая Сильная Неявная Java Статическая Сильная Явная JavaScript Динамическая Слабая Неявная Ruby Динамическая Сильная Неявная PHP Динамическая Слабая Неявная Perl Динамическая Слабая Неявная Haskell Статическая Сильная Неявная Common Lisp Динамическая Сильная Неявная D Статическая Сильная Явная Delphi Статическая Сильная Явная
Примечания:
C# – поддерживает динамическую типизацию посред-
ством специального псевдо-типа
dynamic
живает неявную типизацию с помощью
с версии 4.0. Поддер-
dynamic
и
var
.
С++ – после стандарта C++11 получил поддержку не-
auto
и
явной типизации с помощью ключевых слов
decltype
Поддерживает динамическую типизацию при использовании библиотеки Boost (
boost::any, boost::variant
). Имеет черты как
сильной, так и слабой типизации.
Common Lisp – стандарт предусматривает декларации типов, которые некоторые реализации могут использовать также для статической проверки типов.
D – также поддерживает неявную типизацию.
Delphi – поддерживает динамическую типизацию по- средством специального типа Variant.
.
 
С++
В таблице табл. П3.1 показан приоритет и ассоциатив­ность операторов C++ (в порядке убывания приоритета) [45]. Операторы с тем же номером приоритета имеют равный при­оритет, если другие связи не заданы явно с помощью круг­лых скобок.
Как видно, операции группируются в шестнадцать групп. Рядом с названием каждой группы указано ее свойство – ас­социативность, которая бывает двух видов: слева направо и справа налево. Она применяется в выражениях, где записаны две операции, обладающие одинаковым приоритетом. При­меры обоих видов ассоциативности приводятся в разделе ос­новного текста учебника.
Таблица П3.1
Приоритеты операций с ассоциативностью
и альтернативами
Описание оператора Оператор Альтернатива
Приоритет группы 1, без ассоциативности
1 Разрешение области
Приоритет группы 2, слева направо ассоциативность
2 Выбор члена для указателей (объект
или указатель) 3 Индекс массива 4 Вызов функции 5 Постфиксный инкремент 6 Постфиксный декремент 7 Имя типа 8 Постоянное преобразование типа 9 Динамическое преобразование типа
10 Повторно интерпретируемое преобра-
зование типа
11 Статическое преобразование типа
Приоритет группы 3, справа налево ассоциативность
12 Размер объекта или типа
::
. или ->
[]
()
++
- –
typeid
const_cast
dynamic_cast
reinterpret_cast
static_cast
sizeof
210
АЛГОРИТМИЗАЦИЯ ИПРОГРАММИРОВАНИЕ НАЯЗЫКЕ С++
Продолжение табл. П3.1
Описание оператора Оператор Альтернатива 13 Префиксный инкремент 14 Префиксный декремент 15 Дополнение одного 16 Логический не 17 Унарное отрицание 18 Унарный плюс 19 Взятие адреса 20 Косвенное обращение 21 Создание объекта 22 Уничтожение объекта 23 Cast
Приоритет группы 4, слева направо ассоциативность
24 Указатель на член (объекты или ука-
затели)
Приоритет группы 5, слева направо ассоциативность
25 Умножение 26 Деление 27 Модуль
Приоритет группы 6, слева направо ассоциативность
29 Сложение 30 Вычитание
Приоритет группы 7, слева направо ассоциативность
31 Сдвиг влево 32 Сдвиг вправо
Приоритет группы 8, слева направо ассоциативность
33 Меньше 34 Больше чем 35 Меньше или равно 36 Больше или равно
Приоритет группы 9, слева направо ассоциативность
37 Равенство 38 Неравенство
Приоритет группы 10 слева направо ассоциативность
39 Побитовое И
Приоритет группы 11, слева направо ассоциативность
41 Побитовое исключающее ИЛИ
.* или ->*
++
- –
~ compl
! not
-
+
&
*
new
delete
()
*
/
%
+
-
<<
>>
<
>
<=
>=
==
!= not_eq
& bitand
^ xor
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]