
- •1.2 Философские замечания
- •1.3 Процедурное программирование
- •1.4 Модульное программирование
- •1.5 Абстракция данных
- •1.6 Пределы абстракции данных
- •1.7 Объектно-ориентированное программирование
- •1.8 Концепции объектно-ориентированного программирования
- •1.8.1 Инкапсуляция
- •1.8.2 Полиморфизм
- •1.8.3 Наследование
- •1.10 Несколько полезных советов
- •2.2 Перегрузка функций
- •2.3 Перегрузка операторов
- •2.4 Наследование
- •2.5 Конструкторы и деструкторы
- •2.7 Два новых типа данных
- •Глава 3. Классы и объекты
- •3.1 Параметризованные конструкторы
- •3.2 Дружественные функции
- •3.3 Значения аргументов функции по умолчанию
- •3.3.1 Корректное использование аргументов по умолчанию
- •3.4 Взаимосвязь классов и структур
- •3.5 Связь объединений и классов
- •3.6 Анонимные объединения
- •3.7 Inline-функции
- •3.7.1 Создание inline-функций внутри класса
- •3.8 Передача объектов в функции
- •3.9 Возвращение объектов функциями
- •3.10 Присваивание объектов
- •3.11 Конструктор копирования
- •3.12 Массивы объектов
- •3.12.1 Инициализация массивов объектов
- •3.12.2 Создание инициализированных и неинициализированных массивов
- •3.13 Указатели на объекты
- •3.14 Статические члены класса
- •Глава 4. Перегрузка функций и операторов
- •4.1 Перегрузка конструкторов
- •4.2 Локализация переменных
- •4.3 Локализация создания объектов
- •4.4 Перегрузка функций и неопределенность
- •4.5 Определение адреса перегруженной функции
- •4.6 Указатель this
- •4.7 Перегрузка операторов
- •4.8 Дружественная функция-оператор
- •4.9 Ссылки
- •4.9.1 Параметры-ссылки
- •4.9.2 Передача ссылок на объекты
- •4.9.3 Возврат ссылок
- •4.9.4 Независимые ссылки
- •4.9.5 Использование ссылок для перегрузки унарных операторов
- •4.10 Перегрузка оператора []
- •4.11 Создание функций преобразования типов
- •Глава 5. Наследование, виртуальные функции и полиморфизм
- •5.1 Наследование и спецификаторы доступа
- •5.1.1 Спецификаторы доступа
- •5.1.2 Спецификатор доступа при наследовании базового класса
- •5.1.3 Дополнительная спецификация доступа при наследовании
- •5.2 Конструкторы и деструкторы производных классов
- •5.3 Множественное наследование
- •5.4 Передача параметров в базовый класс
- •5.5 Указатели и ссылки на производные типы
- •5.6 Ссылки на производные классы
- •5.7 Виртуальные функции
- •5.8 Для чего нужны виртуальные функции?
- •5.9 Чисто виртуальные функции и абстрактные типы
- •5.10 Виртуальный базовый класс
- •5.11 Раннее и позднее связывание
- •Глава 6. Подсистема динамического выделения памяти
- •6.1 Введение в обработку исключений
- •6.1.1 Перехват всех исключений
- •6.2 Работа с памятью с помощью new и delete
- •6.3 Размещение объектов
- •6.4 Перегрузка new u delete
- •7.1.1 Потоки
- •7.3 Создание собственных операторов вставки и извлечения
- •7.3.1 Создание операторов вставки
- •7.3.2 Перегрузка операторов извлечения
- •7.4 Форматирование ввода/вывода
- •7.4.1 Форматирование с помощью функций-членов класса ios
- •7.4.2 Использование манипуляторов
- •7.5 Создание собственных функций-манипуляторов
- •7.5.1 Создание манипуляторов без параметров
- •7.5.2 Создание манипуляторов с параметрами
- •7.6 Файловый ввод/вывод
- •7.6.1 Открытие и закрытие файлов
- •7.6.2 Чтение и запись в текстовые файлы
- •7.6.3 Двоичный ввод/вывод
- •7.6.4 Определение конца файла
- •7.6.5 Произвольный доступ
- •Глава 8. Ввод/вывод в массивы
- •8.1 Классы ввода/вывода в массивы
- •8.2 Создание потока вывода
- •8.3 Ввод из массива
- •8.4 Использование функций-членов класса ios
- •8.5 Потоки ввода/вывода в массивы
- •8.6 Произвольный доступ в массив
- •8.7 Использование динамических массивов
- •8.8 Манипуляторы и ввод/вывод в массив
- •8.9 Собственные операторы извлечения и вставки
- •8.10 Форматирование на основе массивов
- •Глава 9. Шаблоны и библиотека stl
- •9.1 Функции-шаблоны
- •9.2 Функции с двумя типами-шаблонами
- •9.3 Ограничения на функции-шаблоны
- •9.4 Классы-шаблоны
- •9.5 Пример с двумя типами-шаблонами
- •9.6 Обзор библиотеки stl
- •9.7 Класс vector
- •9.7 Класс string
- •9.8 Класс list
3.12 Массивы объектов
Можно создавать массивы объектов точно так же, как создаются массивы данных других типов. Например, следующая программа создает класс display, содержащий информацию о различных адаптерах дисплеев, которые могут быть подключены к ПК. В частности, он содержит число цветов, которые могут быть получены, и тип видеоадаптера. В функции main() создается массив из трех объектов display. Доступ к элементам этого массива осуществляется с помощью обычной процедуры с использованием индексов.
#include <iostream.h>
enum disp_type {mono, cga, ega, vga};
class display
{
int colors; // число цветов
enum disp_type dt; // тип дисплея
public:
void set_colors(int num) { colors = num; }
int get_colors() { return colors; }
void set_type(enum disp_type t) { dt = t; }
enum disp_type get_type() { return dt; }
};
char names[4][5] = {"mono", "cga", "ega", "vga"};
int main()
{
display monitors[3];
int i;
monitors[0].set_type(mono); monitors[0].set_colors(1);
monitors[1].set_type(cga); monitors[1].set_colors(4);
monitors[2].set_type(ega); monitors[2].set_colors(16);
for (i = 0; i<3; i++)
{
cout << names[monitors[i].get_type()] << “ “;
cout << "has " << monitors[i].get_colors();
cout << " colors" << "\n";
}
return 0;
}
Эта программа выводит на экран следующий текст:
mono has 1 colors
cga has 4 colors
ega has 16 colors
Хотя это и не относится специально к массивам объектов, обратим внимание, каким образом двумерный символьный массив names использован для преобразования перечисляемых значений к их строковым эквивалентам. Для всех переменных перечисляемого типа, не содержащих явной инициализации, первая константа имеет значение 0, вторая 1 и т. д. Поэтому возвращаемое функцией get_type() значение может быть использовано для индексации массива names, что позволяет вывести подходящее имя.
Многомерные массивы объектов индексируются в точности так же, как и массивы любых других типов данных.
3.12.1 Инициализация массивов объектов
Если класс определяет конструктор с параметрами, то можно инициализировать каждый объект массива путем указания списка инициализации в точности так, как это делается для массивов других типов. Однако точная форма списка инициализации будет определяться числом параметров конструктора. Для объектов, чьи конструкторы имеют только один параметр, можно просто указать список начальных значений, используя обычный синтаксис инициализации массивов. Каждое значение в списке по порядку передается конструктору элемента в массиве при его создании. Например, ниже приведена программа, инициализирующая массив:
#include <iostream.h>
class C
{
int i;
public:
C(int j) { i=j; } // конструктор
int get_i() { return i; }
};
int main()
{
C ob[3] = {1, 2, 3}; // инициализаторы
for(int i=0; i<5; i++)
cout << ob[i].get_i() << "\n";
return 0;
}
Эта программа выводит на экран числа 1, 2 и 3.
Если конструктор объекта требует два или большее число аргументов, тогда необходимо использовать слегка измененную форму инициализации, приведенную ниже:
#include <iostream.h>
class pair
{
int h;
int i;
public:
pair(int j, int k) { h=j; i=k; } // конструктор
int get_i() { return i; }
int get_h() { return h; }
};
int main()
{
pair p[3] = { pair(1,2), pair(3,4), pair(5,6) }; // инициализаторы
for(int i=0; i<3; i++)
{
cout << p[i].get_h() << " ";
cout << p[i].get_i() << "\n";
}
return 0;
}
В этом примере конструктор класса C имеет два параметра и поэтому требует два аргумента. В результате инициализация в укороченной форме записи не может использоваться. Вместо этого применяется инициализация в длинной форме, как показано в примере. Разумеется, можно использовать эту длинную форму инициализации во всех случаях.