Конструкторы и деструкторы в С++
В больших программах в некоторых частях программы обычно требуется инициализация. Необходимость в инициализации еще чаще требуется при работе с объектами. Действительно, фактически, для каждого создаваемого вами объекта требуется какого-то вида инициализация. Для решения этой проблемы в C++ имеется функция-конструктор (constructor function), включаемая в описание класса. Конструктор класса вызывается всякий раз при создании объекта этого класса. Таким образом, любая необходимая объекту инициализация при наличии конструктора выполняется автоматически.
Конструктор имеет то же имя, что и класс, частью которого он является, и не имеет возвращаемого значения. Ниже представлен небольшой класс с конструктором:
В этом простом примере значение а инициализируется конструктором myclass(). Конструктор вызывается тогда, когда создается объект ob. Объект, в свою очередь, создается при выполнении инструкции объявления объекта.
Функцией, обратной конструктору, является деструктор (destructor). Эта функция вызывается при удалении объекта. Обычно при работе с объектом в момент его удаления должны выполняться некоторые действия. Например, при создании объекта для него выделяется память, которую необходимо освободить при его удалении. Имя деструктора совпадает с именем класса, но с символом ~ (тильда) в начале.
В следующем примере показана необходимость не только конструктора, но и деструктора.
Пример. Создается простой класс для строк, который содержит саму строку и ее длину. Когда создается объект strtype, для хранения строки выделяется память, и начальная длина строки устанавливается равной нулю. Когда объект strtype удаляется, эта память освобождается.
Замечание. В этой программе для выделения и освобождения памяти используются функции malloc() и free().
Пример. В программе объект класса timer предназначен для измерения временного интервала между его созданием и удалением. При вызове деструктора на экран выводится прошедшее с момента создания объекта время. Можно воспользоваться подобным объектом для измерения времени работы программы или времени работы функции внутри блока. Объект исчезает в момент завершения временного интервала.
Замечание. В программе используется стандартная библиотечная функция clock(), которая возвращает число временных циклов с момента запуска программы. Если разделить это число на CLOCKS_PER_SEC, можно получить значение в секундах.
Конструктору можно передавать аргументы. Для этого просто добавьте необходимые параметры в объявление и определение конструктора. Затем при объявлении объекта задайте параметры в качестве аргументов.
Пример. Здесь 4 передается в х, а 7 передается в у.
Пример. Здесь представлена следующая версия класса stack, в котором конструктор с параметром используется для присвоения стеку "имени". Это односимвольное имя необходимо для идентификации стека в случае возникновения ошибки.
Пример. Вариант класса strtype, в котором используется конструктор с параметром:
Пример. Объекты могут создаваться по мере необходимости, точно в соответствии с возникающей в момент их создания ситуацией. Конструктору объекта можно передать не только константы, но и любые допустимые выражения с переменными. Например, в следующей программе для создания объекта используется пользовательский ввод:
Конструктор имеет то же имя, что и класс, частью которого он является, и не имеет возвращаемого значения. Ниже представлен небольшой класс с конструктором:
#includeusing namespace std; class myclass { int a; public: myclass (); // конструктор void show() ; myclass :: myclass ( ) { cout ≪ "В конструкторе\n"; a=10; ) void myclass :: show () { cout ≪ a; } int main ( ) { myclass ob; ob. show(); return 0; }
Функцией, обратной конструктору, является деструктор (destructor). Эта функция вызывается при удалении объекта. Обычно при работе с объектом в момент его удаления должны выполняться некоторые действия. Например, при создании объекта для него выделяется память, которую необходимо освободить при его удалении. Имя деструктора совпадает с именем класса, но с символом ~ (тильда) в начале.
В следующем примере показана необходимость не только конструктора, но и деструктора.
Пример. Создается простой класс для строк, который содержит саму строку и ее длину. Когда создается объект strtype, для хранения строки выделяется память, и начальная длина строки устанавливается равной нулю. Когда объект strtype удаляется, эта память освобождается.
#include#include #include using namespace std; #define SIZE 255 class strtype { char *p; int len; public: strtype(); // конструктор ~strtype(); // деструктор void set(char *ptr); void show(); }; // Инициализация объекта строка strtype::strtype() { p=(char *) malloc(SIZE); if(!p) { cout << "Ошибка выделения памяти\n"; exit(1); } *p='\0'; len=0; } // Освобождение памяти при удалении объекта строка strtype::~strtype() { cout << "Освобождение p\n"; free(p); } void strtype::set(char *ptr) { if(strlen(ptr) > SIZE) { cout << "Строка слишком велика\n"; return; } strcpy(p, ptr); len=strlen(p); } void strtype::show() { cout << p << " - длина: " << len; cout << "\n"; } int main() { strtype s1,s2; s1.set("Это проверка"); s2.set("Мне нравится С++"); s1.show(); s2.show(); return 0; }
Пример. В программе объект класса timer предназначен для измерения временного интервала между его созданием и удалением. При вызове деструктора на экран выводится прошедшее с момента создания объекта время. Можно воспользоваться подобным объектом для измерения времени работы программы или времени работы функции внутри блока. Объект исчезает в момент завершения временного интервала.
#include#include using namespace std; class timer { clock_t start; public: timer(); // конструктор ~timer(); // деструктор }; timer::timer() { start=clock(); } timer::~timer() { clock_t end; end=clock(); cout << "Затраченное время: " << (end-start) / CLOCKS_PER_SEC <<"\n"; } int main() { timer ob; char c; // Пауза ... cout << "Нажмите любую клавишу, затем ENTER: "; cin >> c; return 0; }
Конструктору можно передавать аргументы. Для этого просто добавьте необходимые параметры в объявление и определение конструктора. Затем при объявлении объекта задайте параметры в качестве аргументов.
Пример. Здесь 4 передается в х, а 7 передается в у.
#includeusing namespace std; class myclass { int a, b; public: myclass(int x, int y); // конструктор void show(); }; myclass::myclass(int x, int y) { cout << "В конструкторе\n"; a = x; b = y; } void myclass::show() { cout << a << ' ' << b << "\n"; } int main() { myclass ob(4, 7); ob.show(); return 0; }
#includeusing namespace std; #define SIZE 10 // Объявление класса stack для символов class stack { char stck[SIZE]; // содержит стек int tos; // индекс вершины стека char who; // идентифицирует стек public: stack(char c); // конструктор void push(char ch); // помещает в стек символ char pop(); // выталкивает из стека символ }; // Инициализация стека stack::stack(char c) { tos = 0; who = c; cout << "Работа конструктора стека " << who << "\n"; } // Помещение символа в стек void stack::push(char ch) { if (tos==SIZE) { cout << "Стек " << who << " полон \n"; return; } stck[tos]=ch; tos++; } // Выталкивание символа из стека char stack::pop() { if (tos==0) { cout << "Стек " << who << " пуст "; return 0; // возврат нуля при пустом стеке } tos--; return stck[tos]; } int main() { // образование двух, автоматически инициализируемых, // стеков stack s1('A'), s2('B'); int i; s1.push('a'); s2.push('x'); s1.push('b'); s2.push('y'); s1.push('c'); s2.push('z'); // Это вызовет сообщения об ошибках for(i=0; i<5; i++) cout << "символ из стека s1: " << s1.pop() << "\n"; for(i=0; i<5; i++) cout << "символ из стека s2: " << s2.pop() << "\n"; return 0; }
#include#include #include using namespace std; class strtype { char *p; int len; public: strtype(char *ptr); ~strtype(); void show(); }; strtype::strtype(char *ptr) { len = strlen(ptr); p = (char *) malloc(len + 1); if(!p) { cout << "Ошибка выделения памяти\n"; exit(1); } strcpy(p, ptr); } strtype::~strtype() { cout << "Освобождение p\n"; free(p); } void strtype::show() { cout << p << "- длина: " << len; cout << "\n"; } int main() { strtype s1("Это проверка"), s2("Мне нравится С++"); s1.show(); s2.show(); return 0; }
#includeusing namespace std; class myclass { int i, j; public: myclass(int a, int b); void show(); }; myclass::myclass(int a, int b) { i = a; j = b; } void myclass::show() { cout << i << ' ' << j << "\n"; } int main() { int x, y; cout << "Введите два целых: "; cin >> x >> y; // использование переменных для создания ob myclass ob(x, y); ob.show(); return 0; }