Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Алгоритмизация и программирование на языке С++. Ч.1. Учебник
.pdf
Приложение 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] conicting 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] conicting 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
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
