- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Программирование. Принципы и практика использования C++ Исправленное издание - Бьёрн Страуструп
Шрифт:
Интервал:
Закладка:
18.3. Основные операции
Настал момент, когда мы можем приступить к обсуждению того, какие конструкторы должен иметь класс, должен ли он содержать деструктор и требуется ли копирующее присваивание. Следует рассмотреть пять важных операций.
• Конструкторы с одним или несколькими аргументами.
• Конструктор по умолчанию.
• Копирующий конструктор (копирование объектов одинаковых типов).
• Копирующее присваивание (копирование объектов одинаковых типов).
• Деструктор.
Обычно класс должен иметь один или несколько конструкторов, аргументы которых инициализируют объект.
string s(" Триумф "); // инициализируем объект s строкой "Триумф"
vector<double> v(10); // создаем вектор v, состоящий из 10 чисел
// double
Как видим, смысл и использование инициализатора полностью определяются конструктором. Стандартный конструктор класса string использует в качестве начального значения символьную строку, а стандартный конструктор класса vector в качестве параметра получает количество элементов. Обычно конструктор используется для установки инварианта (см. раздел 9.4.3). Если мы не можем определить хороший инвариант для класса, то, вероятно, плохо спроектировали класс или структуру данных.
Конструкторы, имеющие аргументы, сильно зависят от класса, в котором они реализованы. Остальные операции имеют более или менее стандартную структуру.
Как понять, что в классе необходим конструктор по умолчанию? Он требуется тогда, когда мы хотим создавать объекты класса без указания инициализатора. Наиболее распространенный пример такой ситуации возникает, когда мы хотим поместить объекты класса в стандартный контейнер, имеющий тип vector. Приведенные ниже инструкции работают только потому, что для типов int, string и vector<int> существуют значения, предусмотренные по умолчанию.
vector<double> vi(10); // вектор из 10 элементов типа double,
// каждый из них инициализирован 0.0
vector<string> vs(10); // вектор из 10 элементов типа string,
// каждый из них инициализирован ""
vector<vector< int> > vvi(10); // вектор из 10 векторов,
// каждый из них
// инициализирован конструктором vector()
Итак, иметь конструктор по умолчанию часто бывает полезно. Возникает следующий вопрос: а когда именно целесообразно иметь конструктор по умолчанию? Ответ: когда мы можем установить инвариант класса с осмысленным и очевидным значением по умолчанию. Для числовых типов, таких как int и double, очевидным значением является 0 (для типа double оно принимает вид 0.0). Для типа string очевидным выбором является "". Для класса vector можно использовать пустой вектор. Если тип T имеет значение по умолчанию, то оно задается конструктором T(). Например, double() равно 0.0, string() равно "", а vector<int>() — это пустой vector, предназначенный для хранения переменных типа int.
Если класс обладает ресурсами, то он должен иметь деструктор. Ресурс — это то, что вы “где-то взяли” и должны вернуть, когда закончите его использовать. Очевидным примером является память, выделенная с помощью оператора new, которую вы должны освободить, используя оператор delete или delete[]. Для хранения своих элементов наш класс vector требует память, поэтому он должен ее вернуть; следовательно, он должен иметь деструктор. Другие ресурсы, которые используются в более сложных программах, — это файлы (если вы открыли файл, то должны его закрыть), блокировки (locks), дескрипторы потоков (thread handles) и двунаправленные каналы (sockets), используемые для обеспечения взаимосвязи между процессами и удаленными компьютерами.
Другой признак того, что в классе необходим деструктор, — это наличие членов класса, которые являются указателями или ссылками. Если одним из членов класса является указатель или ссылка, скорее всего, в нем требуются деструктор и операции копирования.
Класс, который должен иметь деструктор, практически всегда требует наличия копирующего конструктора и копирующего присваивания. Причина состоит в том, что если объект обладает ресурсом (и имеет указатель — член класса, ссылающийся на это ресурс), то копирование по умолчанию (почленное поверхностное копирование) почти наверняка приведет к ошибке. Классическим примером является класс vector.
Если производный класс должен иметь деструктор, то базовый класс должен иметь виртуальный деструктор (см. раздел 17.5.2).
18.3.1. Явные конструкторы
Конструктор, имеющий один аргумент, определяет преобразование типа этого аргумента в свой класс. Это может оказаться очень полезным. Рассмотрим пример.
class complex {
public:
complex(double); // определяет преобразование double в complex
complex(double,double);
// ...
};
complex z1 = 3.18; // OK: преобразует 3.18 в (3.18,0)
complex z2 = complex(1.2, 3.4);
Однако неявные преобразования следует применять скупо и осторожно, поскольку они могут вызвать неожиданные и нежелательные эффекты. Например, наш класс vector, определенный выше, имеет конструктор, принимающий аргумент типа int. Отсюда следует, что он определяет преобразование типа int в класс vector. Рассмотрим пример.
class vector {
// ...
vector(int);
// ...
};
vector v = 10; // создаем вектор из 10 элементов типа double
v = 20; // присваиваем вектору v новый вектор
// из 20 элементов типа double to v
void f(const vector&);
f(10); // Вызываем функцию f с новым вектором,
// состоящим из 10 элементов типа double
Кажется, мы получили больше, чем хотели. К счастью, подавить такое неявное преобразование довольно просто. Конструктор с ключевым словом explicit допускает только обычную семантику конструирования и не допускает неявные преобразования. Рассмотрим пример.
class vector {
// ...
explicit vector(int);
// ...
};
vector v = 10; // ошибка: преобразования int в vector нет
v = 20; // ошибка: преобразования int

