- •Предисловие
- •Глава 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. Стандартная библиотека шаблонов
- •Литература
- •Предметный указатель
206 15
15.4. Конструкторы
Для инициализации объектов класса создаются специальные функции-члены – конструкторы. Имя конструктора совпадает с именем класса. Конструктор не возвращает никакого значения, даже void. Если класс имеет конструктор, то конструктор вызывается автоматически при создании объекта класса, поэтому все объекты класса будут проинициализированы.
Дополним класс дат конструкторами:
class Date{ |
|
int d, m, y; |
// День, месяц и год |
public: |
|
Date(int, int, int); |
// Конструктор с параметрами (число, месяц, год) |
Date(); |
// Конструктор без параметров (по умолчанию) |
Date(int, int); |
// Конструктор, день, месяц, текущий год |
… |
|
}; |
|
Конструкторов может быть несколько, они различаются по правилам перегруженных функций, то есть по числу и типам аргументов. С целью уменьшения числа конструкторов можно использовать аргументы по умолчанию:
class Date{
int d, m, y; // День, месяц и год public:
Date(int = 0, int = 0, int = 0); // Данный конструктор заменяет три
…
};
Программа 43. Конструкторы в классе дат
Модифицируем программу 42, добавив в класс дат конструктор и функцию увеличения даты на один день.
// Файл DateCl_2.cpp |
|
class Date{ |
|
int d, m, y; |
// День, месяц и год |
public: |
|
Date(int = 0, int = 0, int = 0); |
// Конструктор |
void Add_Year(int n); |
// Добавить к дате n лет |
void Add_Day(); |
// Добавить к дате 1 день |
void Print(); |
|
}; |
|
#include <iostream.h> |
|
Классы 207
void Date::Print()
{
cout << d << '.' << m <<'.'<< y;
}
// leap: возвращает 1, если год year високосный и 0, если нет int leap(int year)
{
return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
}
void Date::Add_Year(int n)
{
if(m == 2 && d == 29 && leap(y + n) != 1){ m = 3;
d = 1;
}
y += n;
}
// Массив дней в месяцах для невисокосного и високосного года char daytab[2][13] ={{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} };
void Date::Add_Day() |
// Добавить к дате 1 день |
{ |
|
if(d < daytab[leap(y)][m]) |
// Если не последний день месяца, |
d++; |
// увеличить номер дня |
else if(m < 12){ |
// Если последний день месяца, но не года, |
|
d = 1; m++; |
// устанавливаем первое число следующего месяца |
|
} |
|
|
else{ |
|
// Если последний день года, |
d = 1; m = 1; y++; |
// устанавливаем 1 января следующего года |
|
} |
|
|
}
При реализации конструктора с аргументами по умолчанию воспользуемся библиотекой с заголовочным файлом dos.h, которая поддерживает, в частности, работу с датами и временем.
В файле dos.h объявлена структура:
struct date |
|
|
{ |
|
|
int |
da_year; |
/* Year – 1980. Текущий год после 1980 */ |
char |
da_day; |
/* Day of the month. День месяца */ |
char |
da_mon; |
/* Month (1 = Jan). Месяц (1 = январь) */ |
}; |
|
|
208 15
Библиотечная функция:
void getdate(struct date *datep);
заполняет поля структуры, на которую указывает datep компонентами текущей даты.
При определении конструктора значения аргументов по умолчанию не указываются. Это делается только один раз при его объявлении.
//Продолжение файла DateCl_2.cpp
//Реализация конструктора #include <dos.h>
Date::Date(int dd, int mm, int yy) |
// Значения аргументов по |
|
{ |
// умолчанию второй раз не указываются |
|
date sysd; |
|
// Системная дата |
getdate(&sysd); |
|
// Получение системной даты |
d = dd ? dd : sysd.da_day; // Если день не задан, берется текущий m = mm ? mm : sysd.da_mon; // Если месяц не задан, берется текущий
y = yy ? yy : sysd.da_year; |
// Если год не задан, берется текущий |
} |
|
#include <conio.h> int main()
{
Date Studies(1, 9, 2005);// Использование конструктора с параметрами cout << "Исходная дата: "; Studies.Print(); cout << endl; Studies.Add_Year(5); // Увеличение даты на 5 лет cout << "Через 5 лет: "; Studies.Print(); cout << endl;
Date Today; // Использование конструктора по умолчанию, сегодня cout << "Сегодня: "; Today.Print(); cout << endl;
Today.Add_Day(); // Завтра cout << "Завтра: "; Today.Print(); cout << endl; Date D(29, 2, 2000);
cout << "Интересная дата: "; D.Print(); cout << endl; D.Add_Day();
cout << "Следующий день: "; D.Print(); cout << endl; getch();
return 0;
}
Программа выдает:
Исходная дата: 1.9.2005 Через 5 лет: 1.9.2010 Сегодня: 29.3.2006 Завтра: 30.3.2006 Интересная дата: 29.2.2000
Классы 209
Следующий день: 1.3.2000
15.5. Статические члены класса
При создании объектов класса каждый объект получает свой полный набор данных-членов класса. Функции-члены класса существуют в одном экземпляре на весь класс и не влияют на размер объектов класса. Убедиться в этом можно с помощью следующей программы.
Программа 44. Размер класса и объектов класса
Перепишем функцию main программы 43 так, чтобы напечатать размер класса Date и размер объектов этого класса. Других изменений в программу 43 не вносим.
// Файл DateCl_3.cpp
/* Здесь поместить объявление класса Date и реализацию функций этого класса из программы 43 */
int main()
{
Date Studies(1, 9, 2005); |
// Некоторая дата |
Date Today; |
// Сегодняшняя дата |
cout << "\nsizeof(Date) = " << sizeof(Date); |
// Размер класса |
cout << "\n sizeof(Today) = " << sizeof(Today); // Размер объекта |
|
Studies.Print(); cout << endl; |
// Вывод некоторой даты |
Today.Print(); cout << endl; |
// Вывод текущей даты |
getch(); return 0;
}
Программа выведет:
sizeof(Date) = 6 sizeof(Today) = 6 1.9.2005 4.4.2006
Видно, что размер класса и размер объектов класса одинаковы и равны 6 байт, так как класс состоит из трех переменных типа int, а в той системе, где выполнялась программа, размер int равен 2 байтам. Функции-члены класса не влияют на размер объектов класса. Они существуют в единственном экземпляре на весь класс, за исключением встроенных функций. Принадлежность функции к классу означает лишь возможность ее доступа к членам класса без явного указания этих членов как аргументов функции.