Начнем с того, что когда мы создаем элементы (переменные) класса, мы не можем присвоить им значения в самом определении класса. Компилятор выдаст ошибку. Поэтому нам необходимо создавать отдельный метод (так называемую set-функцию) класса, с помощью которого и будет происходить инициализация элементов. При этом, если необходимо создать, к примеру, 20 объектов класса, то чтобы инициализировать элементы потребуется 20 раз вызвать set-функции.
Тут нам как раз сможет помочь конструктор класса. Кстати, конструктор (от слова construct — создавать) – это специальный метод класса, который предназначен для инициализации элементов класса некоторыми начальными значениями.
В отличии от конструктора, деструктор (от слова destruct — разрушать) — специальный метод класса, который служит для уничтожения элементов класса. Чаще всего его используют тогда, когда в конструкторе,при создании объекта класса, динамически был выделен участок памяти и необходимо эту память очистить, если эти значения уже не нужны для дальнейшей работы программы.
Важно запомнить:
- конструктор и деструктор, мы всегда объявляем в разделе
public
; - при объявлении конструктора, тип данных возвращаемого значения не указывается, в том числе —
void
!!!; - у деструктора также нет типа данных для возвращаемого значения, к тому же деструктору нельзя передавать никаких параметров;
- имя класса и конструктора должно быть идентично;
- имя деструктора идентично имени конструктора, но с приставкой
~
; - В классе допустимо создавать несколько конструкторов, если это необходимо. Имена, согласно пункту 2 нашего списка, будут одинаковыми. Компилятор будет их различать по передаваемым параметрам (как при перегрузке функций). Если мы не передаем в конструктор параметры, он считается конструктором по умолчанию;
- Обратите внимание на то, что в классе может быть объявлен только один деструктор;
Сразу хочу привести пример, который доступно покажет, как работает конструктор:
# include <iostream> using namespace std; class AB //класс { private: int a; int b; public: AB() //это конструктор: 1) у конструктора нет типа возвращаемого значения! в том числе void!!! // 2) имя должно быть таким как и у класса (в нашем случае AB) { a = 0;//присвоим начальные значения переменным b = 0; cout << "Работа конструктора при создании нового объекта: " << endl;//и здесь же их отобразим на экран cout << "a = " << a << endl; cout << "b = " << b << endl << endl; } void setAB() // с помощью этого метода изменим начальные значения заданные конструктором { cout << "Введите целое число а: "; cin >> a; cout << "Введите целое число b: "; cin >> b; } void getAB() //выведем на экран измененные значения { cout << "a = " << a << endl; cout << "b = " << b << endl << endl; } }; int main() { setlocale(LC_ALL, "rus"); AB obj1; //конструктор сработает на данном этапе (во время создания объекта класса) obj1.setAB(); //присвоим новые значения переменным obj1.getAB(); //и выведем их на экран AB obj2; //конструктор сработает на данном этапе (во время создания 2-го объекта класса) return 0; }
Результат работы программы:
Работа конструктора при создании нового объекта: a = 0 b = 0 Введите целое число а: 34 Введите целое число b: 67 a = 34 b = 67 Работа конструктора при создании нового объекта: a = 0 b = 0
Как видно из результата работы программы, конструктор срабатывает сразу, при создании объектов класса, поэтому, явно вызывать конструктор не нужно, он сам «приходит» :)
Хочется еще добавить, что, как и обычным функциям, мы можем передавать конструктору параметры. Через параметры, конструктору можно передавать любые данные, которые будут необходимы при инициализации объектов класса.
Рассмотрим еще один пример, это все та же программа, только в код внесены некоторые изменения. Тут же покажем принцип работы деструктора:
# include <iostream> using namespace std; class AB //класс { private: int a; int b; public: AB(int A, int B) //эти параметры мы передадим при создании объекта в main { a = A;//присвоим нашим элементам класса значения параметров b = B; cout << "Тут сработал конструктор, который принимает параметры: " << endl;//и здесь же их отобразим на экран cout << "a = " << a << endl; cout << "b = " << b << endl << endl; } void setAB() { cout << "Введите целое число а: "; cin >> a; cout << "Введите целое число b: "; cin >> b; } void getAB() { cout << "a = " << a << endl; cout << "b = " << b << endl << endl; } ~AB() // это деструктор. не будем заставлять его чистить память, пусть просто покажет где он сработал { cout << "Тут сработал деструктор" << endl; } }; int main() { setlocale(LC_ALL, "rus"); AB obj1(100, 100); //передаем конструктору параметры obj1.setAB(); //присвоим новые значения переменным obj1.getAB(); //и выведем их на экран AB obj2(200, 200); //передаем конструктору параметры }
Смотрим результат работы программы:
Тут сработал конструктор, который принимает параметры: a = 100 b = 100 Введите целое число а: 333 Введите целое число b: 333 a = 333 b = 333 Тут сработал конструктор, который принимает параметры: a = 200 b = 200 Тут сработал деструктор Тут сработал деструктор
Деструктор срабатывает в тот момент, когда завершается работа программы и уничтожаются все данные. Мы его не вызывали – он сработал сам. Как видно, он сработал 2 раза, так как и конструктор. Уже от себя добавлю, что, в первую очередь, он удалил второй созданный объект (где a = 200, b = 200), а затем первый (где a = 100, b = 100). «Последним пришёл — первым вышел».
Комментарии
Dharma Cdr
Подскажите пожалуйста. Есть такой интересный момент:
1. Объявление С-строк. Отрабатывает конструктор, выделяя в динамической памяти место и заполняет все позиции »
2. Инициализирую строки с клавиатуры
Проблема возникает, при отработке деструктора, т.к. он пытается освободить память, а расположении строки myStr в памяти уже было изменено. При этом в области видимости деструктора «новое» расположение моей строки прекрасно видно, но отрабатывает с ошибкой «HEAP CORRUPTION» Как обойти эту проблему?
Nicolai Zdravcov
Я не могу понять одно…Обязательно ли указывать конструктор в классе? Насколько я понял указывать его не обязательно, но это дурной тон програмирования. Если нет необходимости, то деструктор указывать необязательно.
Теперь вопрос следующий, если нет необходимости в конструкторе допустимо ли его указывать пустым?
Получается что в привате мы объявляем просто переменные, а в конструкторе их значения. Но ведь можно в какой то из функций класса объявить ихнее значение.
Vova Denys
blablabla
слишком размытое понятие «Конструктора», после 5-ти раз перечитывания данной статьи я так и ничего не понял.