Введение в язык Си++

         

Производные Типы


Вот операции, создающие из основных типов новые типы:



* указатель на
*const константный указатель на
ссылка на
[] вектор
() функция, возвращающая

Например:

char* p // указатель на символ
char *const q // константный указатель на символ
char v[10] // вектор из 10 символов

Все вектора в качестве нижней границы индекса имеют ноль, поэтому в v десять элементов: v[0] ... v[9]. Функции объясняются в #1.5, ссылки в . Переменная указатель может содержать адрес объекта соответствующего типа:

char c; // ... p = c // p указывает на c

Унарное является операцией взятия адреса.


Другие типы модно выводить из основных типов (и типов, определенных пользователем) посредством операций описания:

* указатель
ссылка
[] вектор
() функция

и механизма определения структур. Например:

int* a; float v[10]; char* p[20]; // вектор из 20 указателей на символ void f(int); struct str { short length; char* p; };

Правила построения типов с помощью этих операций подробно объясняются в Основная идея состоит в том, что описание производного типа отражает его использование. Например:

int v[10]; // описывает вектор i = v[3]; // использует элемент вектора

int* p; // описывает указатель i = *p; // использует указываемый объект

Вся сложность понимания записи производных типов проистекает из того, что операции * и префиксные, а операции [] () постфиксные, поэтому для формулировки типов в тех случаях, когда приоритеты операций создают затруднения, надо использовать скобки. Например, поскольку приоритет у [] выше, чем у *, то

int* v[10]; // вектор указателей int (*p)[10]; // указатель на вектор

Большинство людей просто помнят, как выглядят наиболее обычные типы.

Описание каждого имени, вводимого в программе, может оказаться утомительным, особенно если их типы одинаковы. Но можно описывать в одном описании несколько имен. В этом случае описание содержит вместо одного имени список имен, разделенных запятыми. Например, два имени можно описать так:

int x, y; // int x; int y;

При описании производных типов можно указать, что операции применяются только к отдельным именам (а не ко всем остальным именам в этом описании). Например:

int* p, y; // int* p; int y; НЕ int* y; int x, *p; // int x; int* p; int v[10], *p; // int v[10]; int* p;

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




Кроме основных арифметических типов концептуально существует бесконечно много производных типов, сконструированных из основных типов следующим образом:

массивы объектов данного типа;

функции, получающие аргументы данного типа и возвращающие объекты данного типа;

указатели на объекты данного типа;

ссылки на объекты данного типа;

константы, являющиеся значениями данного типа;

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

объединения, являющиеся структурами, которые могут в разное время содержать объекты разных типов.

В целом эти способы конструирования объектов могут применяться рекурсивно.

Объект типа void* (указатель на void) можно использовать для указания на объекты неизвестного типа.



Содержание раздела