- •Классы, Объекты и Методы
- •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;
- •Цепочки методов класса
- •Заключение
Имена деструкторов
Так же, как и конструкторы, деструкторы имеют свои правила, которые касаются их имен:
деструктор должен иметь то же имя, что и класс, со знаком тильда (~) в самом начале;
деструктор не может принимать аргументы;
деструктор не имеет типа возврата.
Из второго правила вытекает еще одно правило: для каждого класса может существовать только один деструктор, так как нет возможности перегрузить деструкторы, как функции, и отличаться друг от друга аргументами они не могут.
Пример использования деструктора на практике
Рассмотрим простой класс с деструктором:
#include <iostream>
#include <cassert>
class Massiv {
private:
int *m_array;
int m_length;
public:
Massiv(int length) { // конструктор
assert(length > 0);
m_array = new int[length];
m_length = length;
}
~Massiv() { // деструктор
// Динамически удаляем массив, который выделили ранее
delete[] m_array ;
}
void setValue(int index, int value) { m_array[index] = value; }
int getValue(int index) { return m_array[index]; }
int getLength() { return m_length; }
};
int main() {
Massiv arr(15); // выделяем 15 целочисленных значений
for (int count=0; count < 15; ++count)
arr.setValue(count, count+1);
std::cout << "The value of element 7 is " << arr.getValue(7);
return 0;
} // объект arr удаляется
Результат выполнения программы:
The value of element 7 is 8
В первой строке функции main() мы создаем новый объект класса Massiv с именем arr и передаем длину (length) 15.
Это приводит к вызову конструктора, который динамически выделяет память для массива класса (m_array).
Мы должны здесь использовать динамическое выделение, поскольку на момент компиляции мы не знаем длину массива (это значение нам передает вызывающая программа).
В конце функции main() объект arr выходит из области видимости. Это приводит к вызову деструктора ~Massiv() и к удалению массива, который мы выделили ранее в конструкторе!
Выполнение конструкторов и деструкторов
Как мы уже знаем, конструктор вызывается при создании объекта, а деструктор — при его уничтожении.
В следующем примере мы будем использовать оператор вывода с cout внутри конструктора и деструктора для отображения их выполнения:
#include <iostream>
class Another {
private:
int m_nID;
public:
Another(int nID) {
std::cout << "Constructing Another " << nID << '\n';
m_nID = nID;
}
~Another() {
std::cout << "Destructing Another " << m_nID << '\n';
}
Int getId() { return m_nId; }
};
Int main() {
// Создаем объект класса Another в стеке
Another object(1);
std::cout << object.getID() << '\n';
// Создаем объект класса Another динамически в кучи
Another *pObject = new Another(2);
std::cout << pObject->getID() << '\n';
delete pObject;
return 0;
} // объект object выходит из области видимости здесь
Результат выполнения программы:
Constructing Another 1
1
Constructing Another 2
2
Destructing Another 2
Destructing Another 1
Обратите внимание, Another 1 уничтожается после Another 2 , так как мы удалили pObject до завершения выполнения функции main(), тогда как объект object не был удален до конца main().
