Конструкторы и деструкторы в С++

В больших программах в некоторых частях программы обычно требуется инициализация. Необходимость в инициализации еще чаще требуется при работе с объектами. Действительно, фактически, для каждого создаваемого вами объекта требуется какого-то вида инициализация. Для решения этой проблемы в C++ имеется функция-конструктор (constructor function), включаемая в описание класса. Конструктор класса вызывается всякий раз при создании объекта этого класса. Таким образом, любая необходимая объекту инициализация при наличии конструктора выполняется автоматически.

Конструктор имеет то же имя, что и класс, частью которого он является, и не имеет возвращаемого значения. Ниже представлен небольшой класс с конструктором:
#include 
using 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;
}
В этом простом примере значение а инициализируется конструктором myclass(). Конструктор вызывается тогда, когда создается объект ob. Объект, в свою очередь, создается при выполнении инструкции объявления объекта.

Функцией, обратной конструктору, является деструктор (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;
}
Замечание. В этой программе для выделения и освобождения памяти используются функции malloc() и free().

Пример. В программе объект класса 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;
}
Замечание. В программе используется стандартная библиотечная функция clock(), которая возвращает число временных циклов с момента запуска программы. Если разделить это число на CLOCKS_PER_SEC, можно получить значение в секундах.

Конструктору можно передавать аргументы. Для этого просто добавьте необходимые параметры в объявление и определение конструктора. Затем при объявлении объекта задайте параметры в качестве аргументов.

Пример. Здесь 4 передается в х, а 7 передается в у.
#include 
using 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;
}
Пример. Здесь представлена следующая версия класса stack, в котором конструктор с параметром используется для присвоения стеку "имени". Это односимвольное имя необходимо для идентификации стека в случае возникновения ошибки.
#include 
using 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;
}
Пример. Вариант класса strtype, в котором используется конструктор с параметром:
#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;
}
Пример. Объекты могут создаваться по мере необходимости, точно в соответствии с возникающей в момент их создания ситуацией. Конструктору объекта можно передать не только константы, но и любые допустимые выражения с переменными. Например, в следующей программе для создания объекта используется пользовательский ввод:
#include 
using 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;
}
Онлайн всего: 27
Гостей: 27
Пользователей: 0

STUDLAB Сообщить про опечатку на сайте