Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


Создание и удаление объектов: конструктор и деструктор



Создание объектов

конструкторов Что такое деструктор

 

 

бъекты в программе создаются и уничтожаются так же, как и объекты  реального мира. Если класс сам отвечает за свое существование, он должен обладать возмож- ностью процессом уничтожения и создания объектов. Программистам на C++ повезло, поскольку C++ предоставляет необходимый для этого механизм (хотя,  скорее всего, это не           а результат разумного планирования языка). Прежде чем начинать соз-

давать и уничтожать объекты в программе, обсудим, что значит "создавать объекты".

 

Создание

Некоторые подчас теряются в терминах класс и объект. В чем разница между эти- ми терминами? Как они связаны?

Я могу  создать  класс            который будет описывать соответствующие свойства лучшего друга человека. К примеру, у меня есть две собаки. Это значит, что мой класс Dog содержит два экземпляра  Труди и Скутер что два: Скутера я не видел уже несколько дней...).

Класс описывает тип предмета, а объект является экземпляром класса. Dog является классом, а Труди и Скутер объектами. Каждая собака представляет собой отдельный объект, но существует только один класс Dog, при этом не имеет значения, сколько у меня собак.

Объекты могут создаваться и уничтожаться, а классы попросту существуют. Мои соба- ки Труди и Скутер приходят и уходят, а класс Dog (оставим эволюцию в стороне) вечен.

Различные типы объектов создаются в разное время. Когда программа начинает выполняться, создаются глобальные объекты. Локальные объекты создаются, когда программа сталкивается с их объявлением.

Глобальный объект является объектом, объявленным вне каких-либо функций. Локальный объект объявляется внутри функции, а

но, является локальным для функции. В приведенном ниже примере пе- ременная    является глобальной, а  переменная                     — локальной по отношению к          ().

int

void pickOne

<

 

 

Глава17.Создание иудалениеобъектов:конструкторидеструктор177


Согласно правилам С глобальные объекты по умолчанию инициализиру- ются нулевыми значениями- Локальные объекты, т.е. объекты,

ные внутри функций, не имеют инициализирующих значений. Такой подход, вообще говоря, для классов неприемлем.

C++ позволяет определить внутри класса специальную функцию-член, которая ав- томатически вызывается при создании объекта этого класса. Эта функция-член назы- вается конструктором и инициализирует объект, приводя его в некоторое необходи- мое начальное состояние. Кроме конструктора, в классе можно определить деструк- тор, который будет вызываться при уничтожении объекта. Эти две функции и являются предметом обсуждения данной главы.

 

Конструктор — это функция-член, которая                           автоматически во время соз- дания объекта соответствующего класса. Основной задачей конструктора является ини- циализация объекта, приводящая его в некоторое корректное начальное состояние.

 

Зачем нужны конструкторы

Объект можно проинициализировать на этапе его объявления, как сделал бы про- граммист на С:

struct Student

{


 

}

void

{

 

 

}


 

float gpa;

 

Student s

//           функции...


Этот фрагмент кода не будет работать для настоящего класса C++, поскольку внешнее приложение не имеет доступа к защищенным членам класса. Приведенный ниже фрагмент некорректен.

class Student

{

 

//        члены...


 

int

 

};


 

gpa;


void

{

Student s =       // неправильно, так как

//         недоступны

//           функции...

 

В данном  случае  функция        не член  п () не имеет права обращаться к членам и      поскольку они являются защищенными (а функция не объяв-

лена в качестве друга класса).

 

 

178                           Часть ///. "Классическое" программирование


Однако, как уже отмечалось, вы можете обеспечить класс инициализирующей функцией, которая будет вызываться в процессе создания объекта. Поскольку эта функция является членом класса, она имеет доступ к защищенным членам. Такой способ инициализации продемонстрирован в приведенном ниже примере.

class


 

public:

void

{

 

 

}


 

 

gpa 0.0;


 

= 0;


//         открытые члены... protected:

 

float gpa;

};

void ()

{

Student s; // создаем объект ... s.init{); // ... и инициализируем его

//           функции...

}

Однако при таком подходе ответственность за инициализацию объекта снимается

с класса. Другими словами, класс должен полагаться на то, что внешнее приложение вызовет функцию-член ini t (). В противном случае объект останется не лизированным и будет содержать непредсказуемые значения.

Для того чтобы избежать этой неприятности, ответственность за вызов инициали- зирующей объект функции необходимо переложить с приложения на компилятор. Всякий раз при создании объекта компилятор может вставлять в код специальную инициализирующую функцию — а это и есть конструктор!

Работа с конструкторами

Конструктор ~ это специальная функция-член, которая автоматически вызы- вается во время создания объекта. Конструктор должен иметь то же имя, что и класс. (Таким образом компилятор сможет определить, что именно эта функ- ция-член является конструктором. Конечно, создатели C++ могли сформулиро- вать это правило как угодно, например, так: "Конструктором является функция с именем Как именно определено правило, не имеет значения; глав- ное — чтобы конструктор мог быть распознан компилятором.) Еще одним свойст- вом конструктора является то, что он не возвращает никакого значения, посколь- ку вызывается автоматически (если бы конструктор и возвращал значение, его все равно некуда было бы записать).

Класс с использованием конструктора продемонстрирован в следующем примере:

 

class

!

 

Student()

{

<< "Конструируем объект Student\n"; semesterHours = 0;

gpa = 0.0;

 

 

Глава17.Создание иудалениеобъектов:конструкторидеструктор179


//                  члены...

 

int

float gpa;

 

 

s; // создаем и инициализируем объект

//           функции...

}

В этом примере компилятор сам  вызывает конструктор                                                (]

в том месте, где объявляется объект s.

Этот простой конструктор реализован в виде встроенной (inline) функции. Конст- руктор можно создать и как обычную функцию с телом, вынесенным из объявления класса:

 

class Student

{

 

//         открытые члены...

 

int

float gpa;

i

Student:    О (

cout << "Конструируем semesterHours =

gpa = 0.0;

 

(]

{

Student s; // создаем и инициализируем объект

//           функции...

int            char*

{

fn(); return 0;

 

В данном примере добавлена небольшая  функция                           чтобы эту тестовую программу можно было запустить. Настоятельно рекомендую пройти эту программу в пошаговом режиме отладчика перед тем, как двигаться дальше.

Инструкции по работе  с  отладчиком                   C++ приведены в главе 29, способов избежать ошибок".

Выполняя этот пример в пошаговом режиме, дойдите до строки с объявлением объекта s. Выполните команду отладчика Шаг с заходом в функции (Step into), и управ- ление как по волшебству перейдет  к () (если у вас inline-версия конструктора, убедитесь, что при компиляции включена опция Outline inline functions, с помощью которой тело функции выносится из объявления класса; в противном случае код конструктора будет подставлен в тело программы и вы не смо- жете попасть в конструктор). Продолжайте выполнение конструктора в пошаговом режиме. Когда функция закончится, управление перейдет к следующей за объявлени- ем объекта класса строке.

 

180                          Часть ///. "Классическое" программирование


В одной             может быть объявлено                      объектов. Выполните, например, о пошаговом режиме следующее:

f. n

 

s [5]; //создаем массив объектов

 

}

Вы увидите пять вызовов конструктора — по одному для каждого элемента


массива.


 

В приведенной далее программе используются команды вывода сообще- информирующие о вызове конструктора, на случай, если вы не мо-

жете (или не хотите) запустить отладчик. Эффект будет хотя и не столь впечатляющим, но от этого не менее убедительным.


Конструктор может быть запущен только автоматически! Нельзя вызывать конст- руктор как обычную функцию-член, а значит, и повторно инициализировать объект класса

 

{

// создаем и инициализируем

//                                    функции...

s .             () ; //                                                                 его,

// но компилятор сообщит об

}

Объявление конструктора не должно содержать тип возвращаемого значения —

и даже тип

Если  класс  имеет                                 которые являются объектами другого класса, конструкторы для этих объектов также будут вызваны автоматически. Обратите вни- мание на следующий пример, в который добавлены команды вывода сообщений, по- зволяющие увидеть, в каком порядке создаются объекты:

induc e                        h>

clas s Student

{

public :

()

{

<< "Конструируем

 

gpa = 0.0;

)

//         открытые члены... protected:

 

};

class

 

<< "Конструируем Teacher\n";

 

class

 

Глава 17. Создание и удаление объектов: конструктор и деструктор 181


public:

 

{

cout << "Конструируем TutorPair\n";

=

)

 

Teacher teacher; int

 

int     argc, char*

{

TutorPair tp;

<< "Возвращаемся в return 0;

}

В результате работы этой программы на экран будут выведены следующие со-

общения: Конструируем Конструируем Teacher

Конструируем TutorPair Возвращаемся в

Создание объекта tp в main;) вызывает конструктор TutorPai r автоматически. Перед тем как управление будет передано телу конструктора TutorPair , вызываются конструкторы для      studen t и teacher .

Конструктор studen t вызывается первым, поскольку объект этого класса объявлен первым. Затем вызывается конструктор Teacher. И только после создания этих объ- ектов управление переходит к конструктору класса TutorPair , который теперь может конструировать оставшуюся часть объекта.

Это не означает, что TutorPai r отвечает за инициализацию объектов studen t и teacher . Каждый класс отвечает за инициализацию своего объекта, где бы тот не создавался.

 

 

Объекты класса уничтожаются так же, как и создаются. Если класс может иметь конструктор для выполнения начальных установок, то он может содержать и специальную функцию для уничтожения объекта. Такая функция-член называ- ется деструктором.

Зачем нужен деструктор

Класс может затребовать для своего объекта некоторые ресурсы с помощью конст- руктора; эти ресурсы должны быть освобождены при уничтожении объекта. Напри- мер, если конструктор открывает файл, перед окончанием работы с объектом класса или программы этот файл следует закрыть. Возможен и другой вариант: если конст- руктор берет память из кучи, то она должна быть освобождена перед тем, как объект перестанет существовать. Деструктор позволяет делать это автоматически, не полага- ясь на вызов необходимых функций-членов в программе.

 

182                             Часть                              программирование


Работа с деструкторами

Деструктор имеет то же имя, что и класс, но только с предшествующим ему сим- волом тильды (-) (C++ последователен и здесь: ведь символ тильды не что иное, как символ оператора "нет", т.е. деструктор — это отрицание конструктора). Как и конст- руктор, деструктор не                            типа возвращаемого значения. С учетом сказанного дест- руктор класса Student будет выглядеть так:

class

{

 

Stucent()

{

= 0;

gpa = 0.0;

}

()

{

//любые         ресурсы освобождаются здесь

}

//                              открытые члены...

 

int

gpa;

} ;

Деструктор вызывается автоматически, когда объект уничтожается или, если гово-

рить языком C++, происходит его деструкция. Чтобы избежать тавтологии ("деструктор вызывается для деструкции объекта"), я по возможности старался не применять этот термин. Можно также сказать "когда объект выходит из области ви- димости". Локальный объект выходит из области видимости, когда функция, создав- шая его, доходит до команды return . Глобальный или статический объект выходит из области видимости, когда прекращается работа программы.

Если уничтожается более одного объекта, деструкторы вызываются в порядке, об- ратном вызову конструкторов. То же касается и случая, когда уничтожаемый объект содержит        Далее приведена программа TutorPair , использующая де- структоры.

<stdio.h>

< ream. class Student

 

 

{

cout << "Конструируем semesterHours =

gpa = 0.0;

}

 

{

cout << "Уничтожаем Student\n";

}

//         открытые члены... protected:

int: semesterHours ; float gpa;

 

Глава17.Создание иудалениеобъектов:конструкторидеструктор183


class Teacher

 

 

Teacher()

cout « "Конструируем Teacher\n";

 

 

cout << "Уничтожаем Teacher\n"; class TutorPair

iс:

 

cout << "Конструируем Tutor?air\n";

 

 

cout << "Уничтожаем TutorPairW ; protected:

Teacher

i. nt        ;

};

in t         (in t               char * pArgs [ ] )

 

TutorPair tp;

cout << "Возвращаемся в return 0;

 

Если вы запустите эту профамму, на экран будуг выведены следующие сообщения:

 

Конструируем Teacher Конструируем TutorPai r Возвращаемся в Уничтожаем

Уничтожаем Уничтожаем Student

Как видите, конструктор класса TutorPai r вызывается при объявлении tp , а дест- руктор — перед завершающей скобкой  функции      . Порядок вызова деструкто- ров                          порядку вызова конструкторов.

 

184                        Часть  "Классическое" программирование


Глава


Поделиться:



Последнее изменение этой страницы: 2019-04-19; Просмотров: 246; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.09 с.)
Главная | Случайная страница | Обратная связь