Изменить стиль страницы

a = 1; a++; *pc = 2; cp = amp;a; cpc++;

Примеры допустимых выражений:

b = a; *cp = a; pc++; pc = cpc; Описание

fseek (FILE*,long,int);

описывает функцию, получающую три параметра указанных типов. Поскольку тип возвращаемого значения не задан, он прнимается int (#8.2). Описание

point (int = 0,int = 0);

описывает функцию, которая может вызываться без парамеров, с одним или с двумя параметрами типа int. Ее можно вызвать одним из следующих способов:

point (1,2); point (1); point ();

Описание

printf (char* ... );

описывает функцию, которая может вызываться с различными числом и типами параметров. Например

printf («hello, world»); printf («a=%d b=%d»,a,b);

Однако, всегда ее первым параметром должен быть char*.

Описание

float fa[17], *afp[17];

описывает массив чисел с плавающей точкой и массив укзателей на числа с плавающей точкой. И, наконец,

static int x3d[3][5][7];

описывает массив целых, размером 3x6x7. Совсем подробно: x3d является массивом из трех элементов данных; каждый из элементов данных является массивом из пяти массивов; каждый из последних массивов является массивом из семи целых. Пояление каждое из выражений x3d, x3d[i], x3d[i][j], x3d[i][j][k] может быть приемлемо в выражении.

8.4.2 Массивы, указатели и индексирование

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

Это правило сообразным образом применяется в случае мнгомерного массива. Если E является n-мерным массивом ранга i* j*...*k, то возникающее в выражении E преобразуется в указтель на (n-1)-мерный массив ранга j*...*k. Если к этому укзателю, явно или неявно, как результат индексирования, примняется операция *, ее результатом является (n-1)-мерный массив, на который указывалось, который сам тут же преобразется в указатель.

Рассмотрим, например,

int x[3][5];

Здесь x – массив целых размером 3*5. Когда x возникает в выражении, он преобразуется в указатель на (первый из трех) 5 – элементный массив из целых. В выражении x[i], которое экввалентно *(x+i), x сначала преобразуется, как было сказано, в указатель, затем i преобразуется к типу x, что включает в сбя умножение i на длину объекта, на который указывает указтель, а именно объект из 5 целых. Результаты складываются, и используется косвенная адресация для получения массива (из 5 целых), который в свою очередь преобразуется в указатель на первое из целых. Если есть еще один индекс, снова используеся тот же параметр; на этот раз результатом является целое.

Именно из всего этого проистекает то, что массивы в С++ хранятся строкообразно (быстрее всего изменяется последний индекс), и что в описании первый индекс помогает определить объем памяти, поглощаемый массивом, но не играет никакой дргой роли в вычислениях индекса.

8.5 Описания классов

Класс есть тип. Его имя становится typedef-имя (см. #8.8), которое может быть использовано даже внутри самого спецификатора класса. Объекты класса состоят из последовтельности членов.

спецификатор_класса: заголовок_класса (* список_членов opt *) заголовок_класса (* список_членов opt public : спсок_членов opt *)

заголовок_класса: сост идентификатор opt сост идентификатор opt : public opt typedef-имя

сост: class struct union

Объекты классов могут присваиваться, передаваться как параметры и возвращаться функциями (за исключением объектов некоторых производных типов, см. #8.5.3). Прочие действия, которые могут быть удобны, может определить пользователь, см. #8.5.11.

Структура является классом, все члены которого общие, см. #8.5.9. Объединение является структурой, содержащей в каждый момент только один член, см. #8.5.13. Список_членов может описывать друзей (8.5.10) и члены вида: данные, фунция, класс, перечисление, поле(#8.5.13). Список_членов может также содержать описания, регулирующие видимость имен членов, см. #8.5.9.

список_членов: описание_члена список_членов opt описание_члена: спецификаторы_описания opt описатель_члена ; определение_функции ; opt описатель_члена: описатель идентификатор opt : константное_выражение

Члены, являющиеся классовыми объектами, должны быть обектами предварительно описанных классов. В частности, класс cl не может содержать объект класса cl, но он может содержать указатель на объект класса cl. Вот простой пример описания структуры:

struct tnode (* char tword[20]; int count; tnode *left; tnode *right; *);

содержащей массив из 20 символов, целое и два указателя на такие же структуры. Если было дано такое описание, то опсание

tnode s, *sp

описывает s как структуру данного сорта и sp как указатель на структуру данного сорта. При наличии этих описаний выражение

sp-»count

ссылается на поле count структуры, на которую указывает sp;

s.left

ссылается на указатель левого поддерва структуры s; а

s.right-»tword[0]

ссылается на первый символ члена tword правого поддерва стрктуры s.

8.5.1 Статические члены

Член данные класса может быть static; члены функции не могут. Члены не могут быть auto, register или extern. Есть единственная копия статического члена, совместно используемая всеми членами класса в программе. На статический член mem класса cl можно ссылаться cl:mem, то есть без ссылки на обект. Он существует, даже если не было создано ни одного обекта класса cl. Для статического члена не может задаваться никакой инициализатор, и он не может быть членом класса с конструктором.

8.5.2 Функции члены

Функция, описанная как член, (без спецификатора friend (#8.5.10)) называется функцией членом и вызывается с исползованием синтаксиса члена класса (#7.1). Например:

struct tnode (* char tword[20]; int count; tnode *left; tnode *right; void set (char* w,tnode* l,tnode* r); *);

tnode n1, n2; n1.set («asdf», amp;n2,0); n2.set («ghjk»,0,0);

Определение функции члена рассматривается как находящеся в области видимости ее класса. Это значит, что она может непосредственно использовать имена ее класса. Если определние функции члена лексически находится вне описания класса, то имя функции члена должно быть уточнено именем класса с пмощью операции ::. Определения функций обсуждаются в #10.

Например:

void tnode.set (char* w,tnode* l,tnode* r) (* count = strlen (w); if (sizeof (tword)«=count) error („tnode string too long“); strcpy (tword,w); left = l; right = r; *)

Запись tnode.set определяет то, что функция set является членом класса tnode и принадлежит его области видисости. Имна членов tword, count, left и right относятся к объекту, для которого была вызвана функция. Так, в вызове n1.set(«abc»,0,0) tword ссылается на n1.tword, а в вызове n2. set(«def»,0,0) оно ссылается на n2.tword. Предполагается, что функции strlen, error и strcpy описаны где-то в другом месте, см. #10.

В функции члене ключевое слово this является указателем на объект, для которого вызвана функция.

Функция член может быть определена (#10) в описании класса, и в этом случак она является inline (#8.1). Например:

int b; struct x (* int f () (* return b; *) int f () (* return b; *) int b; *);

означает

int b; struct x (* int f (); int b; *); inline x::f () (* return b; *)

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