- •Классы, Объекты и Методы
- •Struct DateStruct {
- •Int month;
- •Int year;
- •Методы классов
- •Void print () {
- •Int main () {
- •Int main () {
- •Int main () {
- •Спецификаторы доступа public и private
- •Int year; // открыто по умолчанию
- •Int main () {
- •Int main () {
- •Int main ()
- •Структуры. Классы
- •Инкапсуляция, Геттеры и Сеттеры Инкапсуляция
- •Int m_array[10];
- •Int main () {
- •IntArray array;
- •Void setValue(int index, int value) {
- •Функции доступа (геттеры и сеттеры)
- •Int m_month;
- •Int m_year;
- •Int main () {
- •Краткий обзор l-value и r-value
- •Инициализация ссылок
- •Ссылки в качестве параметров в функциях
- •Void changeN (int &ref) {
- •Int main () {
- •Int value1;
- •Int otherValue;
- •Ссылки. Указатели
- •Конструкторы
- •Int main () {
- •Конструкторы по умолчанию
- •Конструкторы с параметрами
- •Int m_numerator;
- •Int m_denominator;
- •Int getNumerator () {return m_numerator; }
- •Int getDenominator () {return m_denominator; }
- •Копирующая инициализация
- •Уменьшение количества конструкторов
- •Неявно генерируемый конструктор по умолчанию
- •Int main () {
- •Int main () {
- •Классы, содержащие другие классы
- •Int main() {
- •Список инициализации членов класса
- •Списки инициализации членов класса
- •Int m_value1;
- •Values() {
- •Int m_value1;
- •Инициализация массивов в классе
- •Инициализация переменных-членов, которые являются классами
- •Int main() {
- •Использование списков инициализации
- •Int m_value1;
- •Int m_value1;
- •Int m_value1;
- •Порядок выполнения в списке инициализации
- •Инициализация нестатических членов класса
- •Void print() {
- •Int main() {
- •Void print() {
- •Int main() {
- •Void print() {
- •Int main() {
- •Void print() {
- •Int main() {
- •Делегирующие конструкторы
- •Void DoX() {
- •Init();
- •Init();
- •Void Init()
- •Int main() {
- •Ещё о делегирующих конструкторах
- •Деструкторы
- •Имена деструкторов
- •Пример использования деструктора на практике
- •Выполнение конструкторов и деструкторов
- •Int getId() { return m_nId; }
- •Int main() {
- •Предупреждение о функции exit()
- •Скрытый указатель this
- •Скрытый указатель *this
- •Int m_number;
- •Int getNumber() { return m_number; }
- •Int main() {
- •Указатель this всегда указывает на текущий объект. Явное указание указателя this
- •Int data;
- •Цепочки методов класса
- •Заключение
Init();
}
Boo(int value) {
Init();
// Делаем что-либо с value
}
Void Init()
{ // Код инициализации Boo }
};
Здесь мы подключаем функцию Init() для инициализации переменных-членов обратно значениями по умолчанию, а затем каждый конструктор вызывает функцию Init() перед своим фактическим выполнением.
Это сокращает дублирование кода до минимума и позволяет явно вызывать Init() из любого места в программе.
Делегирующие конструкторы в C++11
Начиная с C++11, конструкторам разрешено вызывать другие конструкторы. Этот процесс называется делегированием конструкторов (или «цепочкой конструкторов»).
Чтобы один конструктор вызывал другой, нужно просто сделать вызов этого конструктора в списке инициализации членов.
Например:
class Boo {
private:
public:
Boo() {
// Часть кода X
}
Boo(int value): Boo() // используем конструктор по умолчанию Boo() //для выполнения части кода X
{ // Часть кода Y }
};
Всё работает как нужно. Убедитесь, что вы вызываете конструктор из списка инициализации членов, а не из тела конструктора.
Вот еще один пример использования делегирующих конструкторов для сокращения дублированного кода:
#include <iostream>
#include <string>
class Employee {
private:
int m_id;
std::string m_name;
public:
Employee(int id=0, const std::string &name=""):
m_id(id), m_name(name) {
std::cout << "Employee " << m_name << " created.\n";
}
// Используем делегирующие конструкторы для сокращения //дублированного кода
Employee(const std::string &name) : Employee(0, name) { }
};
Int main() {
Employee a;
Employee b("Ivan");
return 0;
}
Этот класс имеет 2 конструктора (один из которых вызывает другой).
Таким образом, количество дублированного кода сокращено (нам нужно записать только одно определение конструктора вместо двух).
Ещё о делегирующих конструкторах
Во-первых, конструктору, который вызывает другой конструктор, не разрешается выполнять какую-либо инициализацию членов класса.
Поэтому конструкторы могут либо вызывать другие конструкторы, либо выполнять инициализацию, но не всё сразу.
Во-вторых, один конструктор может вызывать другой конструктор, в коде которого может находиться вызов первого конструктора.
Это создаст бесконечный цикл и приведет к тому, что память стека закончится и произойдет сбой.
Вы можете избежать этого, убедившись, что в конструкторе, который вызывается, нет вызова первого (и вообще любого другого) конструктора.
Будьте аккуратны и не используйте вложенные вызовы конструкторов.
Деструкторы
Рассмотрим, что такое деструкторы в языке С++, зачем они нужны, как их использовать и нюансы, которые могут возникнуть при их использовании.
Деструктор — это специальный тип метода класса, который выполняется при удалении объекта класса.
В то время как конструкторы предназначены для инициализации класса, деструкторы предназначены для очистки памяти после удаления его.
Когда объект автоматически выходит из области видимости или
динамически выделенный объект явно удаляется с помощью ключевого слова delete, вызывается деструктор класса (если он существует) для выполнения необходимой очистки до того, как объект будет удален из памяти.
Для простых классов (тех, которые только инициализируют значения обычных переменных-членов) деструктор не нужен, так как C++ автоматически выполнит очистку самостоятельно.
Однако, если объект класса содержит любые ресурсы (например, динамически выделенную память или файл/базу данных), или, если вам необходимо выполнить какие-либо действия до того, как объект будет уничтожен, деструктор является идеальным решением, поскольку он производит последние действия с объектом перед его окончательным уничтожением.
