- •Создание простой программы
- •Компиляция вашей программы
- •Создание второй программы
- •Изучение синтаксических ошибок
- •Что вам необходимо знать
- •Взгляд на операторы программы
- •Представление об операторе #include
- •Что такое void main(void)
- •Использование void
- •If errorlevel 0 if not errorlevel 1 goto successful if errorlevel 1 if not errorlevel 2 goto no_file if errorlevel 2 if not errorlevel 3 goto no_paper rem Далее идут другие команды
- •Представление о группирующих операторах { }
- •Использование cout для отображения вывода на экран
- •Что вы должны знать
- •Урок з. Вывод сообщений на экран
- •Использование cout для вывода чисел
- •Вывод нескольких значений одновременно
- •Использование специальных символов вывода
- •Другие специальные символы
- •Вывод восьмеричных и шестнадцатеричных значений
- •Вывод на стандартное устройство ошибок
- •Управление шириной вывода
- •Что вам необходимо знать
- •Урок 4. Программы хранят информацию в переменных
- •Объявление переменных в программах
- •Смысловые имена переменных
- •Слова, которые нельзя использовать для имен переменных
- •Присваивание значения переменной
- •Присваивание значения при объявлении
- •Использование значения переменной
- •Превышение диапазона значений переменной
- •Представление о точности
- •Использование комментариев для улучшения чтения ваших программ
- •Что вам необходимо знать
- •Урок 5. Выполнение простых операций
- •Основные математические операции
- •Увеличение значения переменной на 1
- •Представление о префиксной (до) и постфиксной (после) операциях увеличения
- •Старшинство операций
- •Следите за ошибками переполнения при арифметических операциях
- •Что вам необходимо знать
- •Урок 6. Чтение ввода с клавиатуры
- •Первое знакомство с cin
- •Следите за ошибками переполнения
- •Следите за ошибками несовпадения типов
- •Чтение символьных данных
- •Чтение слов с клавиатуры
- •Что вам необходимо знать
- •Урок 7. Программа принимает решение
- •Сравнение двух значений
- •Знакомство с оператором if
- •Представление о простых и составных операторах
- •Оператор else
- •Применение составных операторов для else
- •If (условие_истинно) оператор; else оператор;
- •If (условие_истинно)
- •Использование отступов для улучшения удобочитаемости вашей программы
- •Проверка двух или более условий
- •Обработка нескольких условий
- •Использование оператора switch
- •Что вам необходимо знать
- •Урок 8. Повторение одного или нескольких операторов
- •Повторение операторов указанное число раз
- •Изменение и увеличение цикла for
- •Взгляд на цикл while
- •Выполнение операторов по крайней мере один раз
- •Что вам необходимо знать
- •Создание и использование ваших первых функций
- •Программа может передавать информацию в функции
- •Функции могут возвращать результат вызвавшей функции
- •Функции, которые не возвращают значение
- •Использование возвращаемого функцией значения
- •Представление о прототипах функций
- •Что вам необходимо знать
- •Урок 10 изменение значений параметров
- •Почему функции обычно не могут изменить значения параметров
- •Изменение значения параметра
- •Второй пример
- •Что вам необходимо знать
- •Использование функций библиотеки этапа выполнения
- •Изучение функций библиотеки этапа выполнения
- •Что вам необходимо знать
- •Урок 12. Локальные переменные и область видимости
- •Объявление локальных переменных
- •О конфликте имен
- •Глобальные переменные
- •Если имена глобальных и локальных переменных конфликтуют
- •Представление об области видимости переменных
- •Что вам необходимо знать
- •Первое знакомство с перегрузкой функций
- •Когда необходима перегрузка
- •Что вам необходимо знать
- •Ссылка является псевдонимом
- •Использование ссылок в качестве параметров
- •Рассмотрим второй пример
- •Правила работы со ссылками
- •Чт0 вам необходимо знать
- •Урок 15. Значения параметров по умолчанию
- •Определение значений по умолчанию
- •Правила для пропуска значений параметров
- •Что вам необходимо знать
- •Урок 16. Хранение значений в массивах
- •Объявление переменной массива
- •Обращение к элементам массива
- •Использование индексной переменной
- •Инициализация массива при объявлении
- •Передача массивов в функции
- •Что вам необходимо знать
- •Урок 17. Символьные строки
- •Объявление символьных строк в программах
- •Как 'а' отличается от "а"
- •Инициализация символьной строки
- •Передача строк в функции
- •Преимущества того, что null представляет собой ascii 0
- •Использование строковых функций библиотеки этапа выполнения
- •Что вам необходимо знать
- •Урок 18. Хранение связанной информации в структурах
- •Объявление структуры
- •Использование элементов структуры
- •Структуры и функции
- •Функции, изменяющие элементы структуры
- •Что вам необходимо знать
- •Что вам необходимо знать
- •Урок 20. Указатели
- •Использование указателя на символьную строку
- •Второй пример
- •Уменьшение количества операторов
- •Использование указателей с другими типами массивов
- •О математике указателя
- •Что вам необходимо знать
- •Представление об объектах и объектно-ориентированном программировании
- •Определение методов класса вне класса
- •Второй пример
- •Что вам необходимо знать
- •Сокрытие информации
- •Использование общих и частных элементов класса
- •Использование оператора глобального разрешения для элементов класса
- •Частные элементы класса не всегда являются данными
- •Что вам необходимо знать
- •Урок 23. Конструктор и деструктор
- •Создание простого конструктора
- •Конструкторы и параметры по умолчанию
- •Перегрузка конструкторов
- •Представление о деструкторе
- •Что вам необходимо знать
- •Урок 24. Перегрузка операторов
- •Перегрузка операторов плюс и минус
- •Второй пример
- •Операторы, которые Вbl he можете перегрузить
- •Что вам необходимо знать
- •Урок 25. Статические функции и элементы данных
- •Совместное использование элемента данных
- •Использование элементов с атрибутами public static, еслиобъекты не существуют
- •Использование статических функций-элементов
- •Что вам необходимо знать
- •Урок 26. Наследование
- •Простое наследование
- •Второй пример
- •Что такое защищенные элементы
- •Разрешение конфликта имен
- •Что вам необходимо знать
- •Простой пример
- •Построение иерархии классов
- •Что вам необходимо знать
- •Определение друзей класса
- •Ограничение количества друзей
- •Что вам необходимо знать
- •Создание простого шаблона функции
- •Шаблоны, которые используют несколько типов
- •Что вам необходимо знать
- •Создание шаблона класса
- •Что вам необходимо знать
- •Использование оператора new
- •Освобождение памяти, если она больше не нужна
- •Второй пример
- •Что вам необходимо знать
- •Создание обработчика для операций со свободной памятью
- •Создание собственных операторов new Иdelete
- •Что вам необходимо знать
- •Урок 33. Дополнительные возможности cin и cout
- •Что внутри iostream.H
- •Использование cout
- •Использование символа-заполнителя
- •Управление цифрами значений с плавающей точкой
- •Вывод и ввод одного символа за один раз
- •Чтение ввода с клавиатуры по одному символу за раз
- •Чтение с клавиатуры целой строки
- •Что вам необходимо знать
- •Вывод в файловый поток
- •Чтение из входного файлового потока
- •Чтение целой строки файлового ввода
- •Определение конца файла
- •Проверка ошибок при выполнении файловых операций
- •Закрытие файла, если он больше не нужен
- •Управление открытием файла
- •Выполнение операций чтения и записи
- •Что вам необходимо знать
- •Урок 35 встроенные функции и ассемблерные коды
- •Встроенные функции
- •Использование ключевого слова inline
- •Встроенные функции и классы
- •Использование операторов языка ассемблера
- •Что вам необходимо знать
- •Доступ к argv и argc
- •Выполнение цикла, пока argv не содержит null
- •Трактовка argv как указателя
- •Использование аргументов командной строки
- •Доступ к переменным среды операционной системы
- •Что вам необходимо знать
- •Использование именованных констант
- •Использование именованных констант для упрощения изменения кода
- •Замена выражений макрокомандами
- •Чем макрокоманды отличаются от функций
- •Использование макрокоманд предоставляет большую гибкость
- •Что вам необходимо знать
- •Что такое полиморфизм
- •Создание полиморфного объекта-телефона
- •Что такое чисто виртуальные функции
- •Что вам необходимо знать
- •Использование оператора throw для генерации исключительной ситуации
- •Определение обработчика исключительной ситуации
- •Использование элементов данных исключительной ситуации
- •Обработка неожиданных исключительных ситуаций
- •Объявление генерируемых функцией исключительных ситуаций
- •Исключительные ситуации и классы
- •Что вам необходимо знать
Создание обработчика для операций со свободной памятью
Как вы уже знаете из урока 31, если оператор new не может выделить требуемую память из свободной памяти, он присваивает значение NULL вашей переменной-указателю. Следующая программа USE_FREE.CPP неоднократно вызывает оператор new, выделяя каждый раз 1000 байт, пока свободная память не исчерпается:
#include <iostream.h>
void main (void)
{ char *pointer; do
{ pointer = new char[1000]; if (pointer 1= NULL) cout << "Выделено 1000 байт" << endl; else cout << "Свободной памяти нет " << endl; } while (pointer); }
Как видите, программа просто выполняет цикл, пока new не присвоит указателю значение NULL. Если вы хотите, чтобы new выполнил другие действия (что-нибудь отличное от тупого возвращения значения NULL), когда он не может удовлетворить запрос на память, то сначала вам следует определить функцию, которую должна вызывать ваша программа, если памяти недостаточно для удовлетворения запроса. Например, следующая функция end_pro-gram выводит на экран сообщение, а затем использует функцию библиотеки этапа выполнения exit для завершения программы:
void end_program(void)
{ cout << "Запрос на память не может быть удовлетворен" << endl; exit(l); }
Чтобы заставить C++ вызывать функцию end_program, если new не может удовлетворить запрос на память, вам необходимо вызвать функциюset_new_handler, указав ей функцию end_program в качестве параметра, как показано ниже:
set_new_handler(end_program);
Следующая программа END_FREE.CPP вызывает функцию end_program,если new не может удовлетворить запрос на память:
#include <iostream.h>
#include <stdlib.h> // Прототип exit
#include <new.h> // Прототип set_new_handler
void end_program(void)
{ cout << "Запрос на память не может быть удовлетворен" << endl; exit(l); }
void main(void)
{ char* pointer; set_new_handler(end_program); do
{ pointer = new char[10000]; cout << "Выделено 10000 байт" << endl; } while (1); }
В данном случае программа просто завершается, если new не может выделить память из свободной памяти. В зависимости от потребностей вашей программы вы могли бы использовать функцию для выделения памяти из другого источника, например из расширенной памяти компьютера, которая существует в среде MS-DOS. Кроме того, ваша программа могла бы освободить память распределенную ею для других целей, чтобы сделать доступной свободную память. Обеспечивая вашим программам возможность создавать обработчик ситуации отсутствия памяти, C++ предоставляет вам полный контроль над процессом распределения памяти.
Создание собственных операторов new Иdelete
Как вы знаете, C++ позволяет вашим программам перегружать операторы. Аналогично вы можете перегрузить операторы new и delete, чтобы изменить их поведение. Например, предположим, что вы выделяете 100 байт памяти для хранения супер-секретных данных о вашей компании. Когда вы в дальнейшем освобождаете эту память с помощью оператораdelete, освобождается буфер, который содержал эту память, т.е. те самые 100 байт, содержащие супер-секретные данные о вашей компании. Предположим, корпоративный шпион (и программист) имеет доступ к вашему компьютеру, его программа теоретически может распределить тот же 100-байтный массив в памяти вашего компьютера и изучить ваши супер-секреты. Перегружая оператор delete, ваша программа может сначала заполнить этот буфер нулями или другими бессмысленными символами, а потом освободить эту память. Следующая программа MYDELETE.CPP перегружает оператор delete. Она сначала перезаписывает 100 байт, на которые указывает указатель, а затем освобождает память, используя для этого функцию библиотеки этапа выполнения free:
#include <iostream.h>
#include <stdlib.h>
#include <string.h>
static void operator delete(void *pointer)
{ char *data = (char *) pointer; int i; for (i = 0; i < 100; i++) data[i] = 0; cout << "Секрет в безопасности!" << endl; free(pointer); }
void main(void)
{ char *pointer = new char[100]; strcpy(pointer, "Секреты моей компании"); delete pointer; }
При запуске программа выделяет память для строкового массива с помощью оператора new. Затем она копирует секреты компании в эту строку. В дальнейшем программа использует перегруженный операторdelete для освобождения памяти. Внутри функции delete приведенный ниже оператор присваивает значение переменной pointer указателю на символьную строку:
char *data = (char *) pointer;
Символы (char *), которые называются оператором приведения типов,предназначены только для того, чтобы сообщить компилятору C++, что функция знает, что она присваивает указатель типа void (см. выше параметры функции) указателю типа char. Если вы опустите оператор приведения типов, программа не откомпилируется. Затем функция копирует нули в 100 байт буфера и освобождает память, используя для этого функцию библиотеки этапа выполнения free. Очень важно отметить, что эта функция (оператор delete) работает только с областью памяти размером 100 байт. Поскольку данная программа выделяет память только один раз, она работает корректно. Если вы измените программу таким образом, чтобы выделялось только десять байт памяти и не сделаете подобных изменений в этой функции, то она перезапишет 90 байт памяти, которые ваша программа, возможно, использовала для других целей, приведя к ошибке. Однако, используя функции библиотеки этапа выполнения, ваши программы могут получить больше информации о размере области памяти, на которую указывает определенный указатель.
Подобным образом следующая программа NEW_OVER.CPP перегружает оператор C++ new. В данном случае перегруженная функция помещает символьную строку "Учимся программировать на языке C++!" в начало выделяемой памяти:
#include <iostream.h>
#include <alloc.h>
#include <string.h>
static void *operator new(size_t size)
{ char *pointer; pointer = (char *) malloc(size); if (size > strlen( "Учимся программировать на языке C++!")) strcpy(pointer, "Учимся программировать на языке C++!"); return(pointer); }
void main(void)
{ char *str = new char[100]; cout << str << endl; }
Как видите, функция new использует для выделения памяти функциюmalloc библиотеки этапа выполнения. Если размер выделяемой памяти достаточен для хранения строки "Учимся программировать на языке C++!", данная функция использует функцию strcpy библиотеки этапа выполнения для копирования строки в область памяти.