Вызов конструктора и деструктора — КиберПедия 

Наброски и зарисовки растений, плодов, цветов: Освоить конструктивное построение структуры дерева через зарисовки отдельных деревьев, группы деревьев...

Папиллярные узоры пальцев рук - маркер спортивных способностей: дерматоглифические признаки формируются на 3-5 месяце беременности, не изменяются в течение жизни...

Вызов конструктора и деструктора

2020-05-08 175
Вызов конструктора и деструктора 0.00 из 5.00 0 оценок
Заказать работу

Как упоминалось ранее, конструктор и деструктор вызываются в программе автоматически при объявлении объектов класса. Не имеет значения, объявля­ется ли объект явно или создается динамически с помощью new.

Вызов того или иного конструктора зависит от формы описания объекта:

· Если после имени объекта или типа класса в операторе new ничего не указано или стоят пустые круглые скобки, вызовется конструктор по умолчанию.

· Если в скобках записаны параметры, вызывается конструктор с парамет­рами.

· Если в скобках находится имя объекта, то происходит вызов конструктора копирования.

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

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

При объявлении массива указателей на тип класса или единичного указателя никакие конструкторы не вызываются. Они будут вызваны позже при ини­циализации указателей оператором new.

Деструктор вызывается автоматически при разрушении объявленного по имени объекта, поэтому нет необходимости в явном вызове деструктора для разрушения локального объекта или для разрушения объектов перед выхо­дом из программы. Деструктор также вызывается автоматически, когда с по­мощью оператора delete освобождается указатель на объект класса. Без опе­ратора delete объект разрушен не будет. Разрешается и явный вызов деструктора для объекта, который выполняется, как и вызов любого другого метода класса.

Деструкторы вызываются в порядке, обратном порядку объявления имено­ванных объектов в программе. Вызов деструкторов объектов, объявленных через указатели, определяется следованием операторов delete для этих ука­зателей (листинг 14.8).

Иллюстрация вызовов конструкторов и деструктора

// главная функция

#include <iostream>

#include "Book.h"

using namespace std;

// конструктор по умолчанию

CBook::CBook(): m_year(0), m_pTitle("")

{

m_author[0] = '\0';

cout << "default CONSTRUCTORN\nthis = " << this;

}

// конструктор с параметрами

CBook:: CBook (char *author, char *title, int year): m_year (year), m_pTitle (title)

{

strncpy_s (m_author, 50, author, 49);

if (strlen (author) > 49)

m_author[49] = '\0';

cout << "with parameters CONSTRUCTORN\nthis = " << this;

}

// конструктор копирования

CBook:: CBook (CBook &o): m_year (o.m_year) {

strcpy_s (m_author, strlen (o.m_author)+1, o.m_author);

m_pTitle = new char [strlen (o.m_pTitle) + 1 ];

strcpy_s (m_pTitle, strlen (o.m_pTitle) + 1, o.m_pTitle);

cout << "CONSTRUCTOR of copying\nthis = " << this;

}

// деструктор

CBook:: ~CBook ()

{   delete [ ] m_pTltle;

cout << "DESTRUCTOR\t " << this << endl; }

 

void view (char*, CBook&);

int main ()

{

// объявление с вызовом конструктора по умолчанию

CBook book;

book.setAuthor ("Robert Lafore");

book.setTitle ("Object-Oriented Programming in С++");

book.setYear (2004);

view ("book", book);

// объявление с вызовом конструктора с параметрами

CBook obj ("Carrol L.", "Alice in Wonderland", 2002);

view ("obj", obj);

// объявление с вызовом конструктора копирования

CBook copy (obj);

view ("copy obj", copy);

// объявление через указатель с вызовом конструктора с параметрами СВоок *р;.

р = new CBook ("Herbert Schildt", "С++ The Complete Reference", 2003);

view ("pointer p", *p);

// разрушение объекта, объявленного через указатель

delete р;

//return 0;

}

// функция вывода состояния объекта класса СВоок

void view (char *s, CBook &o)

{

cout << "\nState of object V " << s << " \'\n";

cout << "Author:\t" << o.getAuthor () << endl;

cout << "Title:\t" << o.getTitle () << endl;

cout << "Year:\t" << o.getYear () << endl << endl;

}

 

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

В главной функции первым вызывается конструктор по умолчанию, когда объявляется объект book. Далее для объекта book при помощи методов класса setAuthor (), setTitie () и setYear () устанавливаются значения дан­ных m_author, m_pTitie и m_Year, после чего выводится состояние объекта. Вторым вызывается конструктор с параметрами, создающий объект obj с инициализацией данных этого объекта. Третий вызываемый конструктор, который порождает являющийся копией obj объект сору — это конструктор копирования. После вывода состояния сору при помощи оператора динами­ческого выделения памяти и конструктора с параметрами создается объект, адрес которого возвращает оператор new.

Оператор delete в конце программы освобождает указатель р и вызывает деструктор класса, который разрушает последний созданный объект. Далее деструктор автоматически вызывается три раза, разрушая объекты copy, obj и book.

 

Указатель this

Указатель, обозначаемый ключевым словом this, представляет собой неявно определенный указатель на сам объект и является скрытой внутренней пере­менной класса. Отсюда следует:

this — это адрес активного объекта в оперативной памяти.

*this — сам активный объект.

this -> имя члена-данного класса указывает на данное активного объекта. Как правило, this -> не пишется для активного объекта в методах класса, которые обрабатывают это данное активного объекта.

this -> имя метода (список фактических параметров) вызывает метод для активного объекта. Как правило, this -> не пишется при вызове метода активным объектом класса.

Получить значение указателя в методах класса можно с помощью ключе­вого слова this.

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

Абсолютно каждый объект имеет свой собственный указатель this. Этот ука­затель не нужно объявлять в классе, так как объявление имя_класса *const this скрыто в классе как объявление указателя на константу. Для любого принадлежащего классу метода this неявно объявлен точно так же. Изме­нить this невозможно.

 

Статические данные класса

Иногда бывает полезно выделить общую память для всех объектов одного класса. Чтобы получить такую память, следует объявить член-данное со спе­цификатором static. Ключевое слово static помещается перед типом того данного, которое объявляется статическим. Чтобы статические данные клас­са стали доступны за пределами класса, необходимо назначить им открытый спецификатор доступа public. Если же данные объявить закрытыми, то по­требуются открытые методы для получения их значений.

Перечислим основные свойства статических данных класса:

Статические данные не являются частью объектов класса и хранятся за его пределами. Память для статической переменной-члена при объявле­нии объекта класса не выделяется.

Одна копия используется всеми объектами класса, следовательно, все объекты имеют одно и то же значение статического данного.

Объявление статических данных в классе не является их описанием, по­этому присваивание им значений производится вне класса и вне функций программы.

Статические данные существуют даже при отсутствии объектов класса, для которого они объявлены как статические.

Доступ к статической переменной-члену со спецификатором public мо­жет быть реализован без всякого объекта.

#include <iostream>

using namespace std;

class C{

public:

static double A; // открытый статический член-данное

int m_x, m_y; // нестатические члены-данные

private:

static int B;  // закрытый статический член-данное

public:

// конструкторы и деструктор

C(): m_x(0),m_y(0) 

{}

C(int х, int у): m_x (x), m_y (y) 

{}

~C(){       

// метода для статического данного В

    void setB (int _b){B =_b; }

    int getB () { return В; }

};

// инициализация статических данных

//double C:: A = 2.75;

//int C::В = 777;

// главная функция

int main ()

{

С a(10,10), b(-10, -10);

// вывод состояния нестатических данных

cout << "a\t" << a.m_x << '\t' << a.m_y << endl;

cout << "b\t" << b.m_x << '\t' << b.m_y << endl;

// вывод состояния статических данных

cout << "for a and b static A =\t" << C:: A << endl;

cout << "for a static В =\t" << a.getB () << endl;

cout << "for b static В =\t" << b.getB () << endl;

// изменение и вывод значения А

С:: А = 1.2е308;

cout << "after change A =\t" << С:: А << endl; // изменение значения В в объекте а

a.setB (100);

// вывод значения для В для объекта b

cout << "after change in a b.B =\t" << b.getB () << endl;

// изменение значения В в объекте b

b.setB (-100);

// вывод значения В для объекта а

cout << "after change in b а.В =\t" << a.getB () << endl;

}

В классе с в качестве статических данных объявлены открытая а и закрытая в статические переменные. Инициализация значениями проис­ходит за пределами класса и функции main (), как того требуют правила С++. Изменения значения закрытого статического данного в в объекте а отражаются на объекте b, и наоборот. Для доступа к значениям B требуются методы из-за спецификатора private. Доступ к а происходит обычным способом, так как этот статический член-данное имеет спецификатор доступа public.

 

Статические методы класса

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

Существуют следующие ограничения на статические методы:

Методы имеют прямой доступ лишь к статическим данным класса.

Указатель this не виден в статических методах, поэтому в их определении нельзя обратиться к нестатическим данным класса.

Невозможно объявить в классе статическую и нестатическую версии функции.

Статические методы не могут быть виртуальными и не могут быть константными.

Листинг 14.10. Пример класса со статическими методами

#include <iostream>

using namespace std;

class C {

public:

// конструкторы и деструктор

C (char* s) { strcpy_s (m_s, 40, s);

incObj (); }

C ()   

{ m_s [ 0 ] = '\0'; incObj (); }

~C ()  

{ --objAmount; }

// открытые статические методы

static void initAmount (const int v) { objAmount = v; }

static int getAmount ()

{ return objAmount; }

private:

// закрытые статические метод и член-данное

    static int incObj () { return ++objAmount; }

    static int objAmount;

// закрытые нестатический метод и член-данное

    int lenS () 

    {return strlen (m_s); }

    char m_s [ 40 ];

};

// объявление статической переменной

int C:: objAmount;

// главная функция

int main ()

{

C:: initAmount (0); // инициализация objAmount

// объявление и создание объектов

C o1 ("St. Petersburg"), о2 ("Yalta");

C о [ 12 ], о3;

C* р = new C [ 25 ];

// вывод состояния статической переменной

cout << C:: getAmount () << endl; // выводится 40

// разрушение объектов

delete [ ] р;

// вывод состояния статической переменной

cout << C:: getAmount () << endl; // выводится 15

return 0;

}

Для закрытой статической переменной objAmount класса с объявлены три статических метода, два из них являются открытыми, а один — закрытым. Член-данное objAmount используется для подсчета существую­щих в оперативной памяти объектов класса. Для инициализации objAmount целым значением реализован открытый статический метод initAmount (), для получения значения — getAmount (). Закрытый статический метод incObj () предназначен для увеличения на 1 значения статической пере­менной класса objAmount. Этот метод вызывается всеми конструкторами класса. Чтобы программа определяла правильно количество существующих объектов, в деструктор добавлен декремент objAmount.

До начала главной функции объявляется статическая переменная, которая инициализируется первым оператором main (), устанавливая для objAmount нулевое значение. При объявлении объектов ol, о2, оЗ класса с, массива о из 12 объектов и указателя р на массив из 25 объектов типа класса с одно­временной инициализацией автоматически вызываются конструкторы класса, внутри которых инкрементируется число созданных объектов objAmount. Вызов статической функции getAmount () возвращает значение 40, которое выводится. Оператор delete заставит работать деструктор класса, и 25 объ­ектов будут разрушены. Значение objAmount 25 раз уменьшится на 1, после чего повторный вызов getAmount () вернет значение 15.

В связи с тем, что областью видимости статических методов является класс, в котором они объявлены, при всех вызовах указывается оператор расшире­ния области видимости:

С:: initAmount (0); С:: getAmount ();

Если объявить статическую переменную класса objAmount открытой со специ­фикатором public, то можно получить значение без оператора области види­мости, используя любой объект программы. Например, все показанные далее операторы выведут значение objAmount на экран:

cout << р -> objAmount << endl;

cout << ol. objAmount << endl;

cout << о [ 2 ]. objAmount << endl;

cout << о [ 24 ]. objAmount << endl;

 


Поделиться с друзьями:

Двойное оплодотворение у цветковых растений: Оплодотворение - это процесс слияния мужской и женской половых клеток с образованием зиготы...

Индивидуальные очистные сооружения: К классу индивидуальных очистных сооружений относят сооружения, пропускная способность которых...

Особенности сооружения опор в сложных условиях: Сооружение ВЛ в районах с суровыми климатическими и тяжелыми геологическими условиями...

Кормораздатчик мобильный электрифицированный: схема и процесс работы устройства...



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.058 с.