
- •Часть 1
- •Общие сведения Сведения об эумк
- •Методические рекомендации по изучению дисциплины
- •Рабочая учебная программа
- •Учреждение образования
- •«Белорусский государственный университет
- •Информатики и радиоэлектроники»
- •Часть 2 __184__
- •Содержание дисциплины
- •1. Индивидуальные практические занятия, их характеристика
- •2. Контрольные работы, их характеристика
- •3. Курсовой проект, его характеристика
- •4. Литература
- •4.1. Основная
- •4.2. Дополнительная
- •5. Перечень компьютерных программ, наглядных и других пособий, методических указаний и материалов и технических средств обучения
- •Протокол согласования учЕбной программы по изучаемой учебной дисциплине с другими дисциплинами специальности
- •Теоретический раздел Введение
- •1. Основные типы данных
- •1.1. Общие сведения
- •1.2. Данные типа int
- •1.3. Данные типа char
- •1.4. Модификаторы доступа const и volatile
- •1.5. Данные вещественного типа (с плавающей точкой)
- •1.6. Элементарный ввод-вывод
- •1.7. Структура простой программы на языке Си
- •2. Операции и выражения
- •2.1. Выражение и его интерпретация
- •2.2. Основные операции
- •2.2.1. Арифметические операции
- •2.2.2. Побитовые логические операции
- •2.2.3. Операции сдвига
- •2.2.4. Операция присваивания
- •2.2.5. Операция sizeof
- •2.2.6. Преобразование типов в выражениях
- •2.2.7. Операция преобразования типов
- •2.2.8. Приоритеты в языке Си
- •3. Операторы управления вычислительным процессом
- •3.1. Оператор if
- •3.2. Операции отношения
- •3.3. Логические операции
- •3.4. Операция запятая
- •3.5. Операция условия ?:
- •3.6. Оператор безусловного перехода goto
- •3.7. Оператор switch
- •`` ` `3.8. Операторы цикла
- •3.8.1. Оператор for
- •3.8.2. Оператор while
- •3.8.3. Оператор do...While
- •3.9. Оператор break
- •3.10. Оператор continue
- •4. Массивы и указатели
- •4.1. Одномерные массивы и их инициализация
- •4.2. Многомерные массивы и их инициализация
- •4.3. Объявление указателей
- •4.4. Операции над указателями
- •1) Взятие адреса
- •2) Косвенная адресация или разыменование указателя
- •3) Увеличение или уменьшение значения указателя на целое число
- •4) Разность указателей
- •5) Сравнение указателей
- •6) Присваивание указателей друг другу
- •4.6. Связь между указателями и массивами
- •4.7. Динамическое распределение памяти
- •4.8. Массивы указателей
- •5. Функции
- •5.1. Общие сведения
- •5.2. Область видимости переменных
- •5.2.1. Локальные переменные
- •5.2.2. Глобальные переменные
- •5.3. Передача параметров в функцию
- •5.4. Рекурсивные функции
- •5.5. Использование функций в качестве параметров функций
- •5.6. Указатели на функции
- •5.7. Структура программы на Си
- •5.8. Передача параметров в функцию main()
- •6. Строки
- •7. Классы хранения и видимость переменных
- •7.1. Общие сведения
- •7.2. Автоматический класс хранения (auto)
- •7.3. Регистровый класс хранения (register)
- •7.4. Статический класс хранения (static)
- •7.5. Внешний класс хранения (extern)
- •7.6. Заключение
- •8. Структуры, объединения и перечисления
- •8.1. Общие сведения
- •8.2. Инициализация структурных переменных
- •8.3. Вложенные структуры
- •8.4. Указатели на структуры
- •8.5. Массивы структурных переменных
- •8.6. Передача функциям структурных переменных
- •8.7. Оператор typedef
- •8.8. Поля битов в структурах
- •8.9. Объединения
- •8.10. Перечисления
- •9. Динамические структуры данных
- •9.1. Общие сведения
- •9.2. Связные списки
- •9.2.1. Односвязные списки
- •9.2.2. Двусвязные списки
- •9.2.3. Циклические списки
- •9.3. Стеки
- •9.4. Очереди
- •9.5. Деревья
- •9.5.1. Понятие графа
- •9.5.2. Бинарные деревья
- •10. Файлы
- •10.1. Общие сведения
- •10.2. Открытие и закрытие файлов
- •10.3. Функции ввода-вывода для работы с текстовыми файлами
- •10.4. Произвольный доступ к файлу
- •10.5. Функции ввода-вывода для работы с бинарными файлами
- •11. Директивы препроцессора
- •11.1. Основные понятия
- •11.2. Директива #include
- •11.3. Директивы препроцессора #define и #undef
- •11.3.1. Символические константы
- •11.3.2. Макросы с параметрами
- •11.3.3. Директива #undef
- •11.4. Условная компиляция
- •11.5. Директивы # и ##
- •12. Модульное программирование
- •13. Введение в объектно-ориентированное программирование
- •13.1. Постановка задачи
- •13.2. Решение задачи средствами Си
- •13.5. Наследование
- •13.6. Перегрузка
- •13.7. Ссылочный тип
- •Литература
- •Приложение 1. Рекомендации по оформлению текстов программ
- •Тесты к теоретическому разделу Вопросы к разделу 1. Основные типы данных
- •Вопросы к разделу 2. Операции и выражения
- •Вопросы к разделу 3. Операторы управления вычислительным процессом
- •Вопросы к разделу 4. Массивы и указатели
- •Вопросы к разделу 5. Функции
- •Вопросы к разделу 6. Строки
- •Вопросы к разделу 7. Классы хранения и видимость переменных
- •Вопросы к разделу 8. Структуры, объединения и перечисления
- •Вопросы к разделу 9. Динамические структуры данных
- •Вопросы к разделу 10. Файлы
- •Вопросы к разделу 11. Директивы препроцессора
- •Вопросы к разделу 12. Модульное программирование
- •Вопросы к разделу 13. Введение в ооп
- •Правильные ответы на вопросы тестов к теоретическому разделу
- •Вопросы к теоретическому зачету
- •Варианты индивидуальных заданий
- •Контрольная работа №2
- •Варианты индивидуальных заданий
- •Индивидуальные практические работы Указания к выбору варианта индивидуальных практических работ
- •Индивидуальная практическая работа № 1. Массивы и строки
- •Варианты индивидуальных заданий
- •Индивидуальная практическая работа № 2. Динамические структуры данных
- •Варианты индивидуальных заданий
13.6. Перегрузка
Перегрузка – это средство языка C++, позволяющее несколько раз использовать один и тот же идентификатор для схожих логически, но разных формально сущностей. Так, перегрузить функцию означает – создать несколько функций с одинаковым именами, но разными формальными параметрами:
void print(int a); // Вывести на печать число
void print(char c); // Вывести на печать символ
void print(char* s); // Вывести на печать строку
Каноническим является пример функции print. Это очень удобное имя для функции, выводящей что-то на печать. Но если в программе используется несколько функций, одна из которых выводит число, другая – символ и т.д., то в Си придется создать функции с разными именами (printa(int), printc(char), prints(char*), …). Это, в свою очередь, вносит некоторые неудобства при работе с функциями (иногда необходимо иметь достаточно богатую фантазию, чтобы придумывать новые имена, сложно вспомнить, какое имя имеет нужная модификация и т.д.).
С другой стороны, очевидно, что компилятор и сам может выбрать среди предложенных прототипов, какую именно функцию имеет в виду программист:
void f(int a, char c, char* s)
{
// ...
print(a); // Будет вызвана void print(int a)
print(c); // Будет вызвана void print(char c)
print(s); // Будет вызвана void print(char* s)
// ...
}
В случае, когда ни один из прототипов не подходит для вызова (например, при попытке вызова print с параметром типа double или int*) компилятор попытается выполнить неявное преобразование к нужному типу, или, если оно не возможно, констатирует ошибку.
Очевидно, перегрузка функций является развитием принципа полиморфизма в ООП. Перегрузку можно применять и к членам-функциям классов.
13.7. Ссылочный тип
Дополнительно к типу указателя в C++ введен ссылочный тип. Переменная ссылочного типа похожа на переменную указатель, но может быть проинициализирована ссылкой на некоторую переменную (ее адресом) лишь один раз (при объявлении) и, в дальнейшем, не нуждается в операциях раскрытия указателя:
int a = 5; // Переменная целого типа
int *pa = &a; // Указатель на переменную целого типа
int &sa = a; // Ссылка на переменную a (целого типа)
Из данного примера виден синтаксис объявления ссылок. В отличие от объявления указателя идентификатору ссылки предшествует не звёздочка, а амперсанд. Кроме того, как уже было сказано, ссылка должна быть инициализирована при объявлении (заметьте, что в инициализации ссылки, перед идентификатором «a», нет амперсанда).
Работать со ссылочной переменной можно точно так же, как с переменной на которую она ссылается:
void f(int a)
{
int *pa = &a;
int &sa = a;
sa = 3; // Эквивалентно a = 3; или *pa = 3;
// ...
f(sa); // Эквивалентно f(a); или f(*pa);
}
Это средство было бы практически бесполезно, если бы не возможность передавать функции параметры ссылочного типа:
void s_add(int &sa, int b)
{
sa += b;
}
При передаче параметров, переменная b будет передана в функцию через стек по значению, а переменная sa станет ссылкой на первый фактический параметр функции add(). Таким образом, при изменении sa реально изменяется переменная, на которую sa ссылается. Можно говорить что add() является аналогом такой функции использующей указатель:
void p_add(int *pa, int b)
{
*pa += b;
}
Применение ссылки в качестве формального параметра функции изменит и синтаксис ее вызова:
void f(int a, int b)
{
// Вызов с передачей адреса переменной
p_add(&a, b);
// Вызов с «передачей ссылки» на переменную
s_add(a, b);
}
В приведенном примере обе функции изменят значение a, прибавляя к нему b. Не следует, также, забывать и о том, что во втором случае также произошла передача адреса, хотя и в неявной форме.
Имеют смысл, также ссылки на указатели, которые упрощают понимание их назначения. Ниже приведен пример функции, которая создает элемент списка, и изменяет полученный указатель на элемент списка соответствующим образом:
struct TItem *create_item(struct TItem **item,
struct TItem *nxt,
int num)
{
*item = (struct TItem *) malloc(sizeof(struct TItem));
(*item)->number = num;
(*item)->next = nxt;
return *item;
}
Здесь для того, чтобы дать возможность функции изменить при необходимости указатель на элемент списка, используется указатель на указатель. Хотя это вполне простой прием, он делает код непонятным и запутанным. Его можно упростить заменив один из указателей ссылкой:
struct TItem *create_item(struct TItem *&item,
struct TItem *nxt,
int num)
{
item = (struct TItem *) malloc(sizeof(struct TItem));
item->number = num;
item->next = nxt;
return item;
}
Таким образом, использование ссылок упрощает синтаксис функций, которые должны в качестве параметров получать (константные) указатели, а не сами переменные. Следует помнить о том, что нет способа изменить переменную ссылку так, чтобы она ссылалась на другую переменную, нежели указано в объявлении (или при передаче фактического параметра функции).