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

Программирование на языке высокого уровня Лекции 09.03.01

.pdf
Скачиваний:
29
Добавлен:
10.01.2021
Размер:
1.1 Mб
Скачать

} symtab [300];

для ссылки на ival необходимо написать symtab[i].u.ival,

а к первому элементу строки sval можно обратиться любым из двух следующих способов:

*symtab[i].u.sval,

symtab[i].u.sval[0].

Инициализировать объединение можно только значением, имеющим тип его первого члена.

# include <stdio.h> main(){

union tt{

char *fam; float num;

} gg = "gadina"; gg.fam="gaduka"; printf("%s\n",gg.fam); gg.num=45; printf("%f\n",gg.num); printf("%s\n",gg.fam); printf("%f\n",gg.num);

}

Поля битов - это некоторое множество битов, лежащих рядом внутри одного машинного слова. Длина машинного слова зависит от реализации. Синтаксис описания полей битов и доступа к ним также базируется на синтаксисе описания и обработки структурных переменных:

struct {

unsigned int a:1; unsigned int b:1; unsigned int c:2; } flags;

Тут описана переменная flags, которая содержит два однобитовых и одно двухбитовое поле. Числа, следующие за двоеточием, задают ширину поля. Поля, как правило, описываются как беззнаковые целые, но они могут быть и типа int.

На отдельные поля ссылаются точно так же, как на компоненты обычных структурных переменных (например, flags.a). Поля могут участвовать в арифметических операциях так же, как и обычные целые числа. Они не могут быть массивами, не имеют адресов, то есть к ним нельзя применить оператор &.

Тема 26. Переименование типов данных.

Программирование на языке высокого уровня 09.03.01

31

Язык С/С++ предоставляет программисту возможность помимо использования встроенных типов данных, переменных и массивов самому заводить новые типы данных, наиболее подходящие для конкретной задачи. Кроме того в языке существует возможность переименовать любой тип данных, как встроенный, так и определенный программистом. Для этой цели служит средство typedef. Например, описание

typedef int length;

делает имя length синонимом int. С этого момента тип length можно применять при описании, в операторе приведения и т.д., точно так же, как тип int:

length len, maxlen; length *mass;

Аналогично описание

typedef char * string;

делает string синонимом char *, то есть указателем на char, и правомерным будет его соответствующее использование.

Возможно использовать typedef и при работе со структурами: typedef struct point {

int x; int y;

}giena;

Врезультате создается новое название типа - giena, и возможно описание

giena x,y,z;

Следует подчеркнуть, что декларация typedef не создает новый тип, она лишь сообщает новое имя для уже существующего типа. Никакого нового смысла эти новые имена не несут, они описывают переменные в точности с теми же свойствами, как если бы они были объявлены напрямую без переименования типа. Тем не менее, существуют причины для использования в программах средства typedef. Давая типам данных в реальных программах имена, отражающие смысловое содержание предметной области, мы делаем программу более понятной как для самого автора, так и для программистов, которым придется вносить в нее коррективы впоследствии.

typedef int zarplata; typedef struct inform {

char * family; char * addres; int kod;

} information; zarplata x,y;

information a;

Программирование на языке высокого уровня 09.03.01

32

Раздел 4. Структурные особенности языка программирования С++, отсутствующие в С. Лекции

20-22.

Тема 27. Аргументы, используемые по умолчанию.

 

В прототипе функции С++ (кстати, в С++ наличие прототипа

функции является обязательным независимо от типа

значения,

возвращаемого функцией) можно указывать

значения по

умолчанию

для

некоторых

параметров.

Это

позволяет

пропускать

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

Если задан прототип

void ShowMsg (char *msg, int x=0, int y=0);

то корректными будут следующие вызовы:

ShowMsg("Error: Out of Memory"); ShowMsg("Error: Vseh doloy",25); ShowMsg("Error: Domoy ohota",25,25);

А вызов ShowMsg("Error: Vse ravno",,25);

будет неверным.

Тема 28. Встроенные функции.

В С++ при определении функции можно использовать ключевое слово inline. Оно предписывает компилятору помещать расширение тела функции везде, где происходит обращение к ней, вместо того, чтобы генерировать код вызова. Обычно встроенными делаются относительно небольшие по размеру функции, так как их использование делает текст программы больше, хотя такая программа и выполняется быстрее. На содержимое функций, объявляемых как inline, существуют ограничения. Так, не допускается использование ключевого слова inline для функций

применяющих операторы цикла, операторы

switch и goto; для

функций

имеющих тип не void и при этом не содержащих оператора

return.

Кроме того, определение встроенной функции должно

Программирование на языке высокого уровня 09.03.01

33

обязательно предшествовать ее вызову. И вообще, компилятор может безо всяких предупреждений проигнорировать модификатор inline (аналогично модификатору register).

В случае если функция определена как inline, но при ее описании слово inline отсутствует, будет выдано сообщение об ошибке. Если же функция описана как inline, но ее вызов предшествует ее определению, то при этом вызове расширения данной функции как встроенной не произойдет.

# include <stdio.h> inline int max2(int,int); int max3(int,int,int); int main(void)

{int x=10; y=20; z=30; w=40; x=max3(x,z,w);

z=max2(x,y); //расширения не будет

printf("max(%d,%d)=%d\n",x,y,z); return 0;

}

inline int max2(int a, int b)

{return a>b?a:b; }

int max3(int a, int b, int c)

{b=max2(a,b); // будет расширение

return max2(c,b);

}

Тема 29. Ссылки.

В С++ используется видоизмененная форма указателя, называемая ссылкой. Для ссылки не требуется дополнительного пространства в памяти, так как она является просто другим именем или псевдонимом переменной. Для определения ссылки используется унарный оператор &.

# include <stdio.h> int zluka=5;

int &korova=zluka; int main(void) {

printf("zluka=%d\n",zluka); //zluka=5 korova=korova+3; printf("zluka=%d\n",zluka); //zluka=8 return 0; }

Основной смысл использования ссылок состоит в применении их

для параметров функций и для типов

возвращаемых

значений

функций. В том же случае, когда ссылка определена как

псевдоним

Программирование на языке высокого уровня 09.03.01

 

34

переменной, при определении она должна быть инициализирована, если только она не объявлена как extern. Ссылке после инициализации не может быть присвоена другая переменная.

В С++ можно передавать параметры ссылкой. Вызов функции, ожидающей в качестве параметра ссылочную переменную, синтаксически не отличается от вызова, в котором параметр передается значением. Чтобы указать, что функция ожидает передачу параметра ссылкой, при описании при описании перед именем переменной ставится модификатор &. Например,

# include <stdio.h>

 

main() {

 

int j=10;

 

void aaa(int);

 

void bbb(int *);

 

void ccc(int &);

 

printf("j=%d\n",j);

//j=10

aaa(j);

 

printf("j=%d\n",j);

//j=10

bbb(&j);

 

printf("j=%d\n",j);

//j=11

ccc(j);

 

printf("j=%d\n",j);

//j=12

return 0; }

 

void aaa (int i)

 

{i++;}

 

void bbb (int *i)

 

{(*i)++;}

 

void ccc (int &i)

 

{i++;}

 

Главным преимуществом ссылок по сравнению с указателями является простота программы. Во-первых, вызывающей функции не

требуется применять

операцию взятия адреса, а во-вторых,

вызываемая функция

избавлена от использования косвенных

операций.

Ссылка может быть использована как тип, возвращаемый функцией. Это позволяет "присваивать функции значения".

# include <stdio.h> const int j=10;

int mass [j];

int & aaa (int i)

{return mass[i];} void main()

{for (int i=1;i<j;i++) aaa(i)=i*i;

Программирование на языке высокого уровня 09.03.01

35

for (i=1;i<j;i++) printf("mass[%d]=%d\n",i,aaa(i));

}

Таким образом, функция aaa(int) можно применять как для извлечения элемента с определенным индексом, так и для присваивания этому элементу нового значения.

Тема 30. Операция разрешения видимости.

В языке С локальная переменная имеет более высокий приоритет, чем глобальная. С++ позволяет получить доступ к глобальной переменной в пределах области действия локальной переменной. Для этого к имени переменной в любой операции следует применять приставку ::. Данная операция позволяет обращаться к глобальной переменной, даже если переменная с таким же именем определена во внешней локальной области.

# include <stdio.h> int a=10;

int main(void) { int a=100; if(a>0)

{int a=1000; printf("a=%d\n",a); printf("a=%d\n",::a);

}

return 0;

}

Тема 31. Перегруженные функции.

В языке С существует правило, что каждая функция должна иметь уникальное имя. А в С++ существует возможность определить функции с одинаковыми именами, но различными типами аргументов. Эта особенность позволяет использовать одноименные функции для схожих действий, которые необходимо провести над переменными различных типов, что повысит удобочитаемость программы. Компилятор выбирает нужную функцию по соответствию типов аргументов. Таким образом, в программе могут присутствовать прототипы:

void Showmes(int); void Showmes(char*);

Тогда при вызове

Showmes(1)

будет подключаться функция

void Showmes(int nom)

Программирование на языке высокого уровня 09.03.01

36

{printf("Message:%s\n",spisok[nom]);

},

а при вызове Showmes("Ошибка") будет подключена фунция void Showmes(char* msg)

{printf("Message:%s\n",msg);

}

Функции не могут быть перегружены, если их параметры различаются только применением модификатора const или использованием ссылки. Также не могут быть перегружены функции, отличающиеся только типом возвращаемого значения.

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

void fff(int i) int fff(int i) void fff(char i) void fff(char * i)

@fff$qi @fff$qi @fff$qc @fff$gpc.

Программирование на языке высокого уровня 09.03.01

37

Раздел 5. Введение в объектно-ориентированные элементы языка С++ (часть 1) Лекции 23-30.

Тема 32. Определение класса. Понятие о спецификаторах доступа.

Класс можно считать расширением понятия структурного типа,

то

есть типа данных, определяемого пользователем. В С++ при

задании

такого

нового типа

можно задать и некое его поведение,

то

есть определить какие-то функции,

доступные только

для данных

этого

типа.

Переменная,

которая

описывается в

качестве

переменной данного типа, называется представителем класса.

Класс определяется так же как и структура, за исключением того, что:

1) определение класса содержит одну или несколько спецификаций доступа, задаваемых с помощью ключевых слов public, protected или private;

2) наравне с ключевым словом struct могут применяться слова class или union;

3) наряду с элементами данных определение обычно включает в себя элементы-функции (методы);

4) обычно в нем имеются некоторые специальные функции такие, как конструктор (функция с тем же именем, что и класс) и деструктор (функция, именем которой является имя класса с приставкой - символом ~).

Пример определения класса, содержащего только элементы данных:

struct rect

{int x1; int y1; };

Примеры расширенного определения класса: struct point

{ private: int x; int y;

public: int Getx(); int Gety();

void Setx(int); void Sety(int);

}; class line

{point pt1; point pt2;

int width;

public: line (int x; int y); ~line();

Программирование на языке высокого уровня 09.03.01

38

};

В языке С элементы структуры доступны для любой функции в пределах области действия структуры. Это часто приводит к изменению данных из-за невнимательности. В С++ можно ограничить видимость данных и функций класса при помощи меток public, protected и private. Метка - спецификатор доступа применяется ко всем элементам класса, следующим за ней, пока не встретится другая метка или не закончится определение класса. В зависимости от выбранной метки происходит следующее:

при метке private - элементы данных и функции элементы доступны только для функций-элементов этого класса;

при метке public - элементы данных и функции-элементы класса доступны для функций-элементов и других функций программы, в которых имеется представитель класса;

при метке protected - элементы данных и функцииэлементы доступны для функций-элементов данного класса и классов, производных от него.

ВС++ структура, класс и объединение рассматриваются

как типы классов. Структура и класс походят друг на друга за исключением доступа по умолчанию: в структуре элементы имеют по умолчанию доступ public, в то время как в классе - private. Объединение, аналогично структуре, предоставляет по умолчанию доступ public, а в остальном оно ведет себя аналогично объединению в С.

Тема 33. Элементы класса.

Элементы класса делятся на две основные категории: данные,

показывающие состояние

объектов, и

функции, реализующие

поведение

этих объектов.

 

 

Элементы-данные классов С++ похожи

на элементы структур

языка С с

некоторыми дополнениями:

 

элементы-данные не могут объявляться как extern или register;

элементы-данные могут быть перечислениями, битовыми полями, а также представителями ранее объявленных классов;

элементом данных класса не может быть представитель самого этого класса;

элемент данных класса может быть указателем или ссылкой на сам класс.

Элемент-функция является функцией, объявленной (описанной) внутри тела класса. Тело функции тоже может определяться внутри определения класса; такая функция будет являться встроенной функцией-элементом. Если функция определяется вне тела класса, то в заголовке перед именем функции помещается имя класса и

Программирование на языке высокого уровня 09.03.01

39

операция разрешения видимости. Функцию, определенную вне класса тоже можно сделать встроенной, указав в заголовке определения ключевое слово inline.

struct point { private: int x;

int y;

public: int Getx() {.....}//встроенные int Gety() {.....}

void Setx(int); void Sety(int); };

void point::Setx (int xx) // не встроенные {.....}

void point::Sety (int yy) {.....}

Тема 34. Организация доступа к элементам класса.

В языке С имеется несколько разновидностей областей действия для имен: проект, файл, функция, блок. В С++ помимо понятия пространств имен вводится понятие класса как области действия: имена всех элементов класса находятся в области класса - они могут использоваться функциями-элементами класса. Имена элементов класса могут использоваться в следующих случаях:

1)с существующим представителем класса, за которым следует операция доступа к элементу (.);

2)с указателем на существующий представитель класса, за которым следует операция косвенного доступа к элементу (- >);

3)с именем класса, за которым следует операция разрешения видимости.

class coord

{public: int x;

int y;

};

void main (void)

{coord org;

coord * orgptr=&org;

org.x=0; orgptr->y=0;

}

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

Программирование на языке высокого уровня 09.03.01

40