- •Предисловие
- •Глава 1. Основные понятия
- •1.1. Элементы языка программирования
- •1.2. Процесс создания программы
- •1.3. Первая программа
- •1.4. Состав программы
- •Глава 2. Средства разработки на C++
- •2.1. Системы Turbo C++ 3.0/Borland C++ 3.1
- •2.2. Система C++ Builder
- •Глава 3. Работа с числовыми данными
- •3.1. Целые типы
- •3.2. Числа с плавающей точкой
- •3.3. Ввод и вывод чисел
- •3.4. Логический тип и логические операции
- •3.5. Математические функции
- •Глава 4. Операторы. Ключевые слова
- •4.1. Операторы
- •4.2. Приоритеты операторов
- •4.3. Ключевые слова
- •4.4. Структура программы
- •4.5. Константы
- •Задачи - . Простейшие вычисления
- •Глава 5. Управление и циклы
- •5.1. Условный оператор
- •5.2. Операторы цикла
- •5.3. Переключатель
- •5.4. Операторы break и continue
- •Задачи -. Выбор и циклы
- •Глава 6. Массивы
- •6.1. Одномерные массивы
- •6.2. Двумерные массивы
- •Задачи -. Одно- и двумерные массивы
- •Глава 7. Функции
- •7.1. Определение функции
- •7.2. Формальные параметры и фактические аргументы
- •7.3. Автоматические и статические переменные
- •7.4. Прототипы функций
- •7.5. Массивы как аргументы функций
- •7.6. Внешние переменные
- •7.7. Рекурсия
- •7.8. Перегруженные имена функций
- •7.9. Аргументы функций по умолчанию
- •Задачи -. Функции
- •Глава 8. Символы и строки
- •8.1. Символы
- •8.2. Строки символов
- •Задачи -. Символы и строки
- •Глава 9. Препроцессор
- •9.1. Директивы препроцессора
- •9.2. Макросы
- •Задачи -. Макросы
- •Глава 10. Указатели и ссылки
- •10.1. Указатели и адреса
- •10.2. Указатели и массивы
- •10.3. Адресная арифметика
- •10.4. Символьные указатели
- •10.5. Массивы указателей
- •10.6. Указатели на функции
- •10.7. Ссылки
- •10.8. Операторы new и delete
- •Задачи -. Указатели и ссылки
- •Глава 11. О файлах и командной строке
- •11.1. Знакомство с файлами
- •11.2. Командная строка
- •11.3. Перенаправление стандартного ввода и вывода на файл
- •11.4. Аргументы командной строки
- •Задачи -. Файлы и командная строка
- •Глава 12. Работа с экраном дисплея
- •12.1. Текстовый режим
- •12.2. Графический режим
- •Задачи -. Работа с экраном
- •Глава 13. Внутреннее представление чисел
- •13.1. Двоичная система счисления
- •13.2. Беззнаковые целые
- •13.3. Двоичный дополнительный код
- •13.4. Двоичный код с избытком
- •13.5. Побитовые операторы
- •13.6. Дробные числа в двоичной системе
- •13.7. Внутреннее представление плавающих типов
- •13.8. Преобразование типов
- •Задачи -. Побитовые операторы
- •Глава 14. Структуры, перечисления, объединения
- •14.1. Объявление структур
- •14.2. Структуры и функции
- •14.3. Указатели на структуры
- •14.4. Массивы структур
- •14.5. Перечисления
- •14.6. Объединения
- •14.7. Битовые поля
- •14.8. О бинарных файлах
- •Задачи -. Структуры
- •Глава 15. Классы
- •15.1. Структуры в C++. Инкапсуляция
- •15.2. Встроенные функции
- •15.3. Классы. Скрытие данных
- •15.4. Конструкторы
- •15.5. Статические члены класса
- •15.6. Друзья класса
- •15.7. Копирование объектов класса
- •15.8. Управление доступом
- •15.9. Ссылка на себя
- •15.10. Деструкторы
- •Задачи -. Работа с классами
- •Глава 16. Программы из нескольких файлов
- •16.1. Работа с проектами
- •16.2. Область действия имен
- •16.3. Заголовочные файлы
- •16.4. Пространства имен
- •Задачи -. Работа со стеком
- •Глава 17. Перегрузка операторов
- •17.1. Правила перегрузки операторов
- •Задачи -. Перегрузка операторов
- •Глава 18. Конструктор копирования и оператор присваивания
- •18.1. Проблемы при копировании
- •Задачи -. Конструктор копирования
- •Глава 19. Ввод и вывод
- •19.1. Вывод
- •19.2. Ввод
- •19.3. Ввод и вывод определяемых пользователем типов
- •19.4. Работа с файлами
- •Глава 20. Взаимоотношения классов
- •20.1. Объекты как члены класса
- •20.2. Конструкторы встроенных типов
- •20.3. Наследование
- •20.4. Виртуальные функции
- •20.5. Абстрактные классы
- •20.6. Совместимость типов
- •20.7. Множественное наследование
- •Задачи -. Наследование классов
- •Глава 21. Шаблоны, исключения
- •21.1. Шаблоны
- •21.2. Шаблоны функций
- •21.3. Классы и шаблоны
- •21.4. Обработка исключений
- •21.5. Стандартная библиотека шаблонов
- •Литература
- •Предметный указатель
126 10
{
// Исследуем библиотечную функцию синус
cout << "\nmax sin(x) при 0 < x < Pi = " << maxfun(sin, 0, M_PI, 50); // Исследуем функцию erf
cout << "\nmax erf (x) при -2 < x < 2 = " << maxfun(erf, -2, 2, 50); getch();
}
double erf (double x) // Определение функции для исследования
{
return exp(-x * x) / sqrt(2 * M_PI);
}
Внутри maxfun для обращения к функции, максимум которой надо найти, используется просто имя функции f, так как имя функции трактуется как адрес функции и выражения *f и f имеют одинаковое значение адреса функции. Везде, где требуется адрес функции, можно писать просто ее имя и не использовать оператор & перед ним.
Для исследования выбраны библиотечная функция синус и функция erf ( x) = 21π e− x2 .
Данная программа выводит:
max sin(x) при 0 < x < Pi = 0.999486 max erf(x) при -2 < x < 2 = 0.398278
10.7. Ссылки
Ссылка (reference) является альтернативным именем объекта. Пусть X некоторый тип, тогда ссылка на объект типа X объявляется с использованием X&. Например,
void f() |
|
{ |
|
int i =1; |
|
int& r = i; |
// r и i ссылаются на одно и то же целое |
int x = r; |
// x = 1 |
r = 2; |
// i = 2 |
} |
|
Ссылку всегда надо инициализировать, чтобы она ссылалась на какой-нибудь объект, например,
int i = 1; |
|
|
int& r1 = i; |
// Правильно, r1 |
инициализирована |
int& r2; |
// Ошибка, отсутствует инициализация |
|
extern int& r3; |
// Правильно, r3 |
инициализируется в другом месте |
Указатели и ссылки 127
Ссылку можно передавать в функцию в качестве аргумента и возвращать из функции в качестве результата, при этом аргумент, передаваемый в функцию по ссылке, можно изменить внутри функции.
Программа 28. Использование ссылок
В состав программы входит функция swap, меняющая значения своих аргументов, передаваемых в нее по ссылке, и функция max, возвращающая ссылку на максимальный из двух своих аргументов.
// Файл Referenc.cpp
void swap(int& a, int& b) // Обмен значений a и b
{
int tmp = a; a = b;
b = tmp;
}
int& max(int& a, int& b) // Возвращает ссылку на максимальное из a и b
{
return a > b ? a: b;
}
#include <iostream.h> #include <conio.h>
int main()
{
int x, y;
cout << "Введите два числа: "; cin >> x >> y;
cout << "x = " << x << ", y = " << y << endl; swap(x, y);
cout << "После обмена: \n";
cout << "x = " << x << ", y = " << y << endl; max(x, y) = 0;
cout << "Максимальное обнулили: \n";
cout << "x = " << x << ", y = " << y << endl; getch();
return 0;
}
Пример работы программы:
Введите два числа: 2 3 x = 2, y = 3
После обмена: x = 3, y = 2
128 10
Максимальное обнулили: x = 0, y = 2
При вызове функции swap ее параметры a и b инициализируются именами x и y, поэтому a и b становятся другими именами для переменных x и y, что и позволяет изменить x и y внутри функции.
Благодаря тому, что max возвращает ссылку на свой максимальный аргумент, max может стоять в левой части оператора присваивания и максимальному аргументу присваивается новое значение.
Во многих случаях использование ссылок позволяет обойтись без указателей.
10.8. Операторы new и delete
Оператор new выделяет память под объект во время выполнения программы. Например, пусть в программе определен указатель:
double *pd; |
// Указатель на double |
Значение указателя pd после его создания не определено и его использование будет ошибкой. Инструкция:
pd = new double;
выделяет память под double, адрес которой присваивается pd. Теперь выделенную память можно использовать, например:
*pd = sqrt(3); |
// Размещение в памяти значения |
cout << *pd; |
// Печать значения |
После оператора new указывается тип создаваемого объекта. Оператор delete освобождает память, выделенную ранее оператором
new, например, delete pd;
Теперь указатель pd можно использовать для других целей.
Память, освобожденная оператором delete, может быть повторно использована под объекты, создаваемые оператором new.
Динамические массивы можно создавать оператором new[]. Например, массив из 80 символов можно создать инструкцией:
char *s = new char[80];
Для удаления динамических массивов служит оператор delete[], например,
delete[] s; // Удаление массива s
Указатели и ссылки 129
При освобождении памяти, выделенной оператором new, операторы delete и delete[] должны иметь возможность определять размер удаляемого объекта. Это обеспечивается тем, что под динамический объект памяти выделяется больше, чем под статический, обычно на одно слово, в котором хранится размер объекта.
Программа 29. Выделение и освобождение памяти
В данной программе демонстрируется выделение и освобождение памяти. Для наблюдения за адресами использован оператор вывода <<, который по умолчанию выводит адреса как целые десятичные числа.
// Файл AllocMem.cpp |
|
#include <iostream.h> |
|
#include <math.h> |
|
int main() |
|
{ |
|
double *pd; |
// Указатель |
// Вывод адреса, хранящегося в pd |
|
cout << hex << "\n Address(pd) = " << pd;
pd = new double; |
// Выделение памяти |
*pd = sqrt(3); |
// Занесение в память значения |
// Вывод адреса и значения |
|
cout << "\n Address(pd) = " << pd << ", Value(*pd) = " << *pd;
char *s; |
// Символьный указатель |
cout << "\n Address(s) = " << (int*)s; |
|
delete pd; |
// Освобождение памяти |
s = new char[80]; |
// Создание динамического массива |
cout << "\n Address(s) = " << (int*)s << ", Value(s) = " << s; |
|
cout << "\n Input a string \n"; |
// Введите строку |
cin.getline(s, 80); |
// Использование памяти |
cout << "Address(s) = " << (int*)s << ", Value(s) = " << s; cin.get();
return 0;
}
Программа выводит следующее:
Address(pd) = 1
Address(pd) = 8f5fc0, Value(*pd) = 1.73205 Address(s) = 100
Address(s) = 8f5fc0, Value(s) = ∟vg2∟vg2 Input a string
qwerty
Address(s) = 8f5fc0, Value(s) = qwerty